1 // -*- mode: cpp; mode: fold -*-
3 // $Id: pkgcache.cc,v 1.37 2003/02/10 01:40:58 doogie Exp $
4 /* ######################################################################
6 Package Cache - Accessor code for the cache
8 Please see doc/apt-pkg/cache.sgml for a more detailed description of
9 this format. Also be sure to keep that file up-to-date!!
11 This is the general utility functions for cache management. They provide
12 a complete set of accessor functions for the cache. The cacheiterators
13 header contains the STL-like iterators that can be used to easially
14 navigate the cache as well as seemlessly dereference the mmap'd
15 indexes. Use these always.
17 The main class provides for ways to get package indexes and some
18 general lookup functions to start the iterators.
20 ##################################################################### */
22 // Include Files /*{{{*/
25 #include <apt-pkg/pkgcache.h>
26 #include <apt-pkg/policy.h>
27 #include <apt-pkg/version.h>
28 #include <apt-pkg/error.h>
29 #include <apt-pkg/strutl.h>
30 #include <apt-pkg/configuration.h>
31 #include <apt-pkg/aptconfiguration.h>
32 #include <apt-pkg/mmap.h>
33 #include <apt-pkg/macros.h>
49 // Cache::Header::Header - Constructor /*{{{*/
50 // ---------------------------------------------------------------------
51 /* Simply initialize the header */
52 pkgCache::Header::Header()
54 #define APT_HEADER_SET(X,Y) X = Y; static_assert(std::numeric_limits<decltype(X)>::max() > Y, "Size violation detected in pkgCache::Header")
55 APT_HEADER_SET(Signature
, 0x98FE76DC);
57 /* Whenever the structures change the major version should be bumped,
58 whenever the generator changes the minor version should be bumped. */
59 APT_HEADER_SET(MajorVersion
, 10);
60 APT_HEADER_SET(MinorVersion
, 3);
61 APT_HEADER_SET(Dirty
, false);
63 APT_HEADER_SET(HeaderSz
, sizeof(pkgCache::Header
));
64 APT_HEADER_SET(GroupSz
, sizeof(pkgCache::Group
));
65 APT_HEADER_SET(PackageSz
, sizeof(pkgCache::Package
));
66 APT_HEADER_SET(ReleaseFileSz
, sizeof(pkgCache::ReleaseFile
));
67 APT_HEADER_SET(PackageFileSz
, sizeof(pkgCache::PackageFile
));
68 APT_HEADER_SET(VersionSz
, sizeof(pkgCache::Version
));
69 APT_HEADER_SET(DescriptionSz
, sizeof(pkgCache::Description
));
70 APT_HEADER_SET(DependencySz
, sizeof(pkgCache::Dependency
));
71 APT_HEADER_SET(DependencyDataSz
, sizeof(pkgCache::DependencyData
));
72 APT_HEADER_SET(ProvidesSz
, sizeof(pkgCache::Provides
));
73 APT_HEADER_SET(VerFileSz
, sizeof(pkgCache::VerFile
));
74 APT_HEADER_SET(DescFileSz
, sizeof(pkgCache::DescFile
));
96 SetHashTableSize(_config
->FindI("APT::Cache-HashTableSize", 15013));
97 memset(Pools
,0,sizeof(Pools
));
102 // Cache::Header::CheckSizes - Check if the two headers have same *sz /*{{{*/
103 // ---------------------------------------------------------------------
105 bool pkgCache::Header::CheckSizes(Header
&Against
) const
107 if (HeaderSz
== Against
.HeaderSz
&&
108 GroupSz
== Against
.GroupSz
&&
109 PackageSz
== Against
.PackageSz
&&
110 ReleaseFileSz
== Against
.ReleaseFileSz
&&
111 PackageFileSz
== Against
.PackageFileSz
&&
112 VersionSz
== Against
.VersionSz
&&
113 DescriptionSz
== Against
.DescriptionSz
&&
114 DependencySz
== Against
.DependencySz
&&
115 DependencyDataSz
== Against
.DependencyDataSz
&&
116 VerFileSz
== Against
.VerFileSz
&&
117 DescFileSz
== Against
.DescFileSz
&&
118 ProvidesSz
== Against
.ProvidesSz
)
124 // Cache::pkgCache - Constructor /*{{{*/
125 // ---------------------------------------------------------------------
127 APT_IGNORE_DEPRECATED_PUSH
128 pkgCache::pkgCache(MMap
*Map
, bool DoMap
) : Map(*Map
), d(NULL
)
130 // call getArchitectures() with cached=false to ensure that the
131 // architectures cache is re-evaulated. this is needed in cases
132 // when the APT::Architecture field changes between two cache creations
133 MultiArchEnabled
= APT::Configuration::getArchitectures(false).size() > 1;
137 APT_IGNORE_DEPRECATED_POP
139 // Cache::ReMap - Reopen the cache file /*{{{*/
140 // ---------------------------------------------------------------------
141 /* If the file is already closed then this will open it open it. */
142 bool pkgCache::ReMap(bool const &Errorchecks
)
144 // Apply the typecasts.
145 HeaderP
= (Header
*)Map
.Data();
146 GrpP
= (Group
*)Map
.Data();
147 PkgP
= (Package
*)Map
.Data();
148 VerFileP
= (VerFile
*)Map
.Data();
149 DescFileP
= (DescFile
*)Map
.Data();
150 RlsFileP
= (ReleaseFile
*)Map
.Data();
151 PkgFileP
= (PackageFile
*)Map
.Data();
152 VerP
= (Version
*)Map
.Data();
153 DescP
= (Description
*)Map
.Data();
154 ProvideP
= (Provides
*)Map
.Data();
155 DepP
= (Dependency
*)Map
.Data();
156 DepDataP
= (DependencyData
*)Map
.Data();
157 StrP
= (char *)Map
.Data();
159 if (Errorchecks
== false)
162 if (Map
.Size() == 0 || HeaderP
== 0)
163 return _error
->Error(_("Empty package cache"));
167 if (HeaderP
->Signature
!= DefHeader
.Signature
||
168 HeaderP
->Dirty
== true)
169 return _error
->Error(_("The package cache file is corrupted"));
171 if (HeaderP
->MajorVersion
!= DefHeader
.MajorVersion
||
172 HeaderP
->MinorVersion
!= DefHeader
.MinorVersion
||
173 HeaderP
->CheckSizes(DefHeader
) == false)
174 return _error
->Error(_("The package cache file is an incompatible version"));
176 if (Map
.Size() < HeaderP
->CacheFileSize
)
177 return _error
->Error(_("The package cache file is corrupted, it is too small"));
179 if (HeaderP
->VerSysName
== 0 || HeaderP
->Architecture
== 0 || HeaderP
->GetArchitectures() == 0)
180 return _error
->Error(_("The package cache file is corrupted"));
183 if ((VS
= pkgVersioningSystem::GetVS(StrP
+ HeaderP
->VerSysName
)) == 0)
184 return _error
->Error(_("This APT does not support the versioning system '%s'"),StrP
+ HeaderP
->VerSysName
);
186 // Check the architecture
187 std::vector
<std::string
> archs
= APT::Configuration::getArchitectures();
188 std::vector
<std::string
>::const_iterator a
= archs
.begin();
189 std::string list
= *a
;
190 for (++a
; a
!= archs
.end(); ++a
)
191 list
.append(",").append(*a
);
192 if (_config
->Find("APT::Architecture") != StrP
+ HeaderP
->Architecture
||
193 list
!= StrP
+ HeaderP
->GetArchitectures())
194 return _error
->Error(_("The package cache was built for different architectures: %s vs %s"), StrP
+ HeaderP
->GetArchitectures(), list
.c_str());
199 // Cache::Hash - Hash a string /*{{{*/
200 // ---------------------------------------------------------------------
201 /* This is used to generate the hash entries for the HashTable. With my
202 package list from bo this function gets 94% table usage on a 512 item
203 table (480 used items) */
204 map_id_t
pkgCache::sHash(const string
&Str
) const
206 uint32_t Hash
= 5381;
207 for (string::const_iterator I
= Str
.begin(); I
!= Str
.end(); ++I
)
208 Hash
= 33 * Hash
+ tolower_ascii(*I
);
209 return Hash
% HeaderP
->GetHashTableSize();
212 map_id_t
pkgCache::sHash(const char *Str
) const
214 uint32_t Hash
= 5381;
215 for (const char *I
= Str
; *I
!= 0; ++I
)
216 Hash
= 33 * Hash
+ tolower_ascii(*I
);
217 return Hash
% HeaderP
->GetHashTableSize();
220 // Cache::FindPkg - Locate a package by name /*{{{*/
221 // ---------------------------------------------------------------------
222 /* Returns 0 on error, pointer to the package otherwise */
223 pkgCache::PkgIterator
pkgCache::FindPkg(const string
&Name
) {
224 size_t const found
= Name
.find(':');
225 if (found
== string::npos
)
226 return FindPkg(Name
, "native");
227 string
const Arch
= Name
.substr(found
+1);
228 /* Beware: This is specialcased to handle pkg:any in dependencies
229 as these are linked to virtual pkg:any named packages.
230 If you want any arch from a pkg, use FindPkg(pkg,"any") */
232 return FindPkg(Name
, "any");
233 return FindPkg(Name
.substr(0, found
), Arch
);
236 // Cache::FindPkg - Locate a package by name /*{{{*/
237 // ---------------------------------------------------------------------
238 /* Returns 0 on error, pointer to the package otherwise */
239 pkgCache::PkgIterator
pkgCache::FindPkg(const string
&Name
, string
const &Arch
) {
240 /* We make a detour via the GrpIterator here as
241 on a multi-arch environment a group is easier to
242 find than a package (less entries in the buckets) */
243 pkgCache::GrpIterator Grp
= FindGrp(Name
);
244 if (Grp
.end() == true)
245 return PkgIterator(*this,0);
247 return Grp
.FindPkg(Arch
);
250 // Cache::FindGrp - Locate a group by name /*{{{*/
251 // ---------------------------------------------------------------------
252 /* Returns End-Pointer on error, pointer to the group otherwise */
253 pkgCache::GrpIterator
pkgCache::FindGrp(const string
&Name
) {
254 if (unlikely(Name
.empty() == true))
255 return GrpIterator(*this,0);
257 // Look at the hash bucket for the group
258 Group
*Grp
= GrpP
+ HeaderP
->GrpHashTableP()[sHash(Name
)];
259 for (; Grp
!= GrpP
; Grp
= GrpP
+ Grp
->Next
) {
260 int const cmp
= strcmp(Name
.c_str(), StrP
+ Grp
->Name
);
262 return GrpIterator(*this, Grp
);
267 return GrpIterator(*this,0);
270 // Cache::CompTypeDeb - Return a string describing the compare type /*{{{*/
271 // ---------------------------------------------------------------------
272 /* This returns a string representation of the dependency compare
273 type in the weird debian style.. */
274 const char *pkgCache::CompTypeDeb(unsigned char Comp
)
276 const char * const Ops
[] = {"","<=",">=","<<",">>","=","!="};
277 if (unlikely((unsigned)(Comp
& 0xF) >= sizeof(Ops
)/sizeof(Ops
[0])))
279 return Ops
[Comp
& 0xF];
282 // Cache::CompType - Return a string describing the compare type /*{{{*/
283 // ---------------------------------------------------------------------
284 /* This returns a string representation of the dependency compare
286 const char *pkgCache::CompType(unsigned char Comp
)
288 const char * const Ops
[] = {"","<=",">=","<",">","=","!="};
289 if (unlikely((unsigned)(Comp
& 0xF) >= sizeof(Ops
)/sizeof(Ops
[0])))
291 return Ops
[Comp
& 0xF];
294 // Cache::DepType - Return a string describing the dep type /*{{{*/
295 // ---------------------------------------------------------------------
297 const char *pkgCache::DepType(unsigned char Type
)
299 const char *Types
[] = {"",_("Depends"),_("PreDepends"),_("Suggests"),
300 _("Recommends"),_("Conflicts"),_("Replaces"),
301 _("Obsoletes"),_("Breaks"), _("Enhances")};
302 if (Type
< sizeof(Types
)/sizeof(*Types
))
307 // Cache::Priority - Convert a priority value to a string /*{{{*/
308 // ---------------------------------------------------------------------
310 const char *pkgCache::Priority(unsigned char Prio
)
312 const char *Mapping
[] = {0,_("required"),_("important"),_("standard"),
313 _("optional"),_("extra")};
314 if (Prio
< _count(Mapping
))
315 return Mapping
[Prio
];
319 // GrpIterator::FindPkg - Locate a package by arch /*{{{*/
320 // ---------------------------------------------------------------------
321 /* Returns an End-Pointer on error, pointer to the package otherwise */
322 pkgCache::PkgIterator
pkgCache::GrpIterator::FindPkg(string Arch
) const {
323 if (unlikely(IsGood() == false || S
->FirstPackage
== 0))
324 return PkgIterator(*Owner
, 0);
326 /* If we accept any package we simply return the "first"
327 package in this group */
329 return PkgIterator(*Owner
, Owner
->PkgP
+ S
->FirstPackage
);
330 if (Arch
== "native" || Arch
== "all")
331 Arch
= Owner
->NativeArch();
333 // Iterate over the list to find the matching arch
334 for (pkgCache::Package
*Pkg
= PackageList(); Pkg
!= Owner
->PkgP
;
335 Pkg
= Owner
->PkgP
+ Pkg
->NextPackage
) {
336 if (stringcmp(Arch
, Owner
->StrP
+ Pkg
->Arch
) == 0)
337 return PkgIterator(*Owner
, Pkg
);
338 if ((Owner
->PkgP
+ S
->LastPackage
) == Pkg
)
342 return PkgIterator(*Owner
, 0);
345 // GrpIterator::FindPreferredPkg - Locate the "best" package /*{{{*/
346 // ---------------------------------------------------------------------
347 /* Returns an End-Pointer on error, pointer to the package otherwise */
348 pkgCache::PkgIterator
pkgCache::GrpIterator::FindPreferredPkg(bool const &PreferNonVirtual
) const {
349 pkgCache::PkgIterator Pkg
= FindPkg("native");
350 if (Pkg
.end() == false && (PreferNonVirtual
== false || Pkg
->VersionList
!= 0))
353 std::vector
<std::string
> const archs
= APT::Configuration::getArchitectures();
354 for (std::vector
<std::string
>::const_iterator a
= archs
.begin();
355 a
!= archs
.end(); ++a
) {
357 if (Pkg
.end() == false && (PreferNonVirtual
== false || Pkg
->VersionList
!= 0))
360 // packages without an architecture
361 Pkg
= FindPkg("none");
362 if (Pkg
.end() == false && (PreferNonVirtual
== false || Pkg
->VersionList
!= 0))
365 if (PreferNonVirtual
== true)
366 return FindPreferredPkg(false);
367 return PkgIterator(*Owner
, 0);
370 // GrpIterator::NextPkg - Locate the next package in the group /*{{{*/
371 // ---------------------------------------------------------------------
372 /* Returns an End-Pointer on error, pointer to the package otherwise.
373 We can't simply ++ to the next as the next package of the last will
374 be from a different group (with the same hash value) */
375 pkgCache::PkgIterator
pkgCache::GrpIterator::NextPkg(pkgCache::PkgIterator
const &LastPkg
) const {
376 if (unlikely(IsGood() == false || S
->FirstPackage
== 0 ||
377 LastPkg
.end() == true))
378 return PkgIterator(*Owner
, 0);
380 if (S
->LastPackage
== LastPkg
.Index())
381 return PkgIterator(*Owner
, 0);
383 return PkgIterator(*Owner
, Owner
->PkgP
+ LastPkg
->NextPackage
);
386 // GrpIterator::operator++ - Prefix incr /*{{{*/
387 // ---------------------------------------------------------------------
388 /* This will advance to the next logical group in the hash table. */
389 pkgCache::GrpIterator
& pkgCache::GrpIterator::operator++()
391 // Follow the current links
392 if (S
!= Owner
->GrpP
)
393 S
= Owner
->GrpP
+ S
->Next
;
395 // Follow the hash table
396 while (S
== Owner
->GrpP
&& (HashIndex
+1) < (signed)Owner
->HeaderP
->GetHashTableSize())
399 S
= Owner
->GrpP
+ Owner
->HeaderP
->GrpHashTableP()[HashIndex
];
404 // PkgIterator::operator++ - Prefix incr /*{{{*/
405 // ---------------------------------------------------------------------
406 /* This will advance to the next logical package in the hash table. */
407 pkgCache::PkgIterator
& pkgCache::PkgIterator::operator++()
409 // Follow the current links
410 if (S
!= Owner
->PkgP
)
411 S
= Owner
->PkgP
+ S
->NextPackage
;
413 // Follow the hash table
414 while (S
== Owner
->PkgP
&& (HashIndex
+1) < (signed)Owner
->HeaderP
->GetHashTableSize())
417 S
= Owner
->PkgP
+ Owner
->HeaderP
->PkgHashTableP()[HashIndex
];
422 pkgCache::DepIterator
& pkgCache::DepIterator::operator++() /*{{{*/
424 if (S
== Owner
->DepP
)
426 S
= Owner
->DepP
+ (Type
== DepVer
? S
->NextDepends
: S
->NextRevDepends
);
427 if (S
== Owner
->DepP
)
428 S2
= Owner
->DepDataP
;
430 S2
= Owner
->DepDataP
+ S
->DependencyData
;
434 // PkgIterator::State - Check the State of the package /*{{{*/
435 // ---------------------------------------------------------------------
436 /* By this we mean if it is either cleanly installed or cleanly removed. */
437 pkgCache::PkgIterator::OkState
pkgCache::PkgIterator::State() const
439 if (S
->InstState
== pkgCache::State::ReInstReq
||
440 S
->InstState
== pkgCache::State::HoldReInstReq
)
443 if (S
->CurrentState
== pkgCache::State::UnPacked
||
444 S
->CurrentState
== pkgCache::State::HalfConfigured
)
445 // we leave triggers alone complettely. dpkg deals with
446 // them in a hard-to-predict manner and if they get
447 // resolved by dpkg before apt run dpkg --configure on
448 // the TriggersPending package dpkg returns a error
449 //Pkg->CurrentState == pkgCache::State::TriggersAwaited
450 //Pkg->CurrentState == pkgCache::State::TriggersPending)
451 return NeedsConfigure
;
453 if (S
->CurrentState
== pkgCache::State::HalfInstalled
||
454 S
->InstState
!= pkgCache::State::Ok
)
460 // PkgIterator::CandVersion - Returns the candidate version string /*{{{*/
461 // ---------------------------------------------------------------------
462 /* Return string representing of the candidate version. */
464 pkgCache::PkgIterator::CandVersion() const
466 //TargetVer is empty, so don't use it.
467 VerIterator version
= pkgPolicy(Owner
).GetCandidateVer(*this);
468 if (version
.IsGood())
469 return version
.VerStr();
473 // PkgIterator::CurVersion - Returns the current version string /*{{{*/
474 // ---------------------------------------------------------------------
475 /* Return string representing of the current version. */
477 pkgCache::PkgIterator::CurVersion() const
479 VerIterator version
= CurrentVer();
480 if (version
.IsGood())
481 return CurrentVer().VerStr();
485 // ostream operator to handle string representation of a package /*{{{*/
486 // ---------------------------------------------------------------------
487 /* Output name < cur.rent.version -> candid.ate.version | new.est.version > (section)
488 Note that the characters <|>() are all literal above. Versions will be omitted
489 if they provide no new information (e.g. there is no newer version than candidate)
490 If no version and/or section can be found "none" is used. */
492 operator<<(std::ostream
& out
, pkgCache::PkgIterator Pkg
)
494 if (Pkg
.end() == true)
495 return out
<< "invalid package";
497 string current
= string(Pkg
.CurVersion() == 0 ? "none" : Pkg
.CurVersion());
498 string candidate
= string(Pkg
.CandVersion() == 0 ? "none" : Pkg
.CandVersion());
499 string newest
= string(Pkg
.VersionList().end() ? "none" : Pkg
.VersionList().VerStr());
501 out
<< Pkg
.Name() << " [ " << Pkg
.Arch() << " ] < " << current
;
502 if (current
!= candidate
)
503 out
<< " -> " << candidate
;
504 if ( newest
!= "none" && candidate
!= newest
)
505 out
<< " | " << newest
;
506 if (Pkg
->VersionList
== 0)
507 out
<< " > ( none )";
509 out
<< " > ( " << string(Pkg
.VersionList().Section()==0?"unknown":Pkg
.VersionList().Section()) << " )";
513 // PkgIterator::FullName - Returns Name and (maybe) Architecture /*{{{*/
514 // ---------------------------------------------------------------------
515 /* Returns a name:arch string */
516 std::string
pkgCache::PkgIterator::FullName(bool const &Pretty
) const
518 string fullname
= Name();
519 if (Pretty
== false ||
520 (strcmp(Arch(), "all") != 0 && strcmp(Arch(), "any") != 0 &&
521 strcmp(Owner
->NativeArch(), Arch()) != 0))
522 return fullname
.append(":").append(Arch());
526 // DepIterator::IsCritical - Returns true if the dep is important /*{{{*/
527 // ---------------------------------------------------------------------
528 /* Currently critical deps are defined as depends, predepends and
529 conflicts (including dpkg's Breaks fields). */
530 bool pkgCache::DepIterator::IsCritical() const
532 if (IsNegative() == true ||
533 S2
->Type
== pkgCache::Dep::Depends
||
534 S2
->Type
== pkgCache::Dep::PreDepends
)
539 // DepIterator::IsNegative - Returns true if the dep is a negative one /*{{{*/
540 // ---------------------------------------------------------------------
541 /* Some dependencies are positive like Depends and Recommends, others
542 are negative like Conflicts which can and should be handled differently */
543 bool pkgCache::DepIterator::IsNegative() const
545 return S2
->Type
== Dep::DpkgBreaks
||
546 S2
->Type
== Dep::Conflicts
||
547 S2
->Type
== Dep::Obsoletes
;
550 // DepIterator::SmartTargetPkg - Resolve dep target pointers w/provides /*{{{*/
551 // ---------------------------------------------------------------------
552 /* This intellegently looks at dep target packages and tries to figure
553 out which package should be used. This is needed to nicely handle
554 provide mapping. If the target package has no other providing packages
555 then it returned. Otherwise the providing list is looked at to
556 see if there is one one unique providing package if so it is returned.
557 Otherwise true is returned and the target package is set. The return
558 result indicates whether the node should be expandable
560 In Conjunction with the DepCache the value of Result may not be
561 super-good since the policy may have made it uninstallable. Using
562 AllTargets is better in this case. */
563 bool pkgCache::DepIterator::SmartTargetPkg(PkgIterator
&Result
) const
565 Result
= TargetPkg();
567 // No provides at all
568 if (Result
->ProvidesList
== 0)
571 // There is the Base package and the providing ones which is at least 2
572 if (Result
->VersionList
!= 0)
575 /* We have to skip over indirect provisions of the package that
576 owns the dependency. For instance, if libc5-dev depends on the
577 virtual package libc-dev which is provided by libc5-dev and libc6-dev
578 we must ignore libc5-dev when considering the provides list. */
579 PrvIterator PStart
= Result
.ProvidesList();
580 for (; PStart
.end() != true && PStart
.OwnerPkg() == ParentPkg(); ++PStart
);
582 // Nothing but indirect self provides
583 if (PStart
.end() == true)
586 // Check for single packages in the provides list
587 PrvIterator P
= PStart
;
588 for (; P
.end() != true; ++P
)
590 // Skip over self provides
591 if (P
.OwnerPkg() == ParentPkg())
593 if (PStart
.OwnerPkg() != P
.OwnerPkg())
597 Result
= PStart
.OwnerPkg();
599 // Check for non dups
606 // DepIterator::AllTargets - Returns the set of all possible targets /*{{{*/
607 // ---------------------------------------------------------------------
608 /* This is a more useful version of TargetPkg() that follows versioned
609 provides. It includes every possible package-version that could satisfy
610 the dependency. The last item in the list has a 0. The resulting pointer
611 must be delete [] 'd */
612 pkgCache::Version
**pkgCache::DepIterator::AllTargets() const
615 unsigned long Size
=0;
619 PkgIterator DPkg
= TargetPkg();
621 // Walk along the actual package providing versions
622 for (VerIterator I
= DPkg
.VersionList(); I
.end() == false; ++I
)
624 if (IsIgnorable(I
.ParentPkg()) == true)
626 if (IsSatisfied(I
) == false)
634 // Follow all provides
635 for (PrvIterator I
= DPkg
.ProvidesList(); I
.end() == false; ++I
)
637 if (IsIgnorable(I
) == true)
639 if (IsSatisfied(I
) == false)
644 *End
++ = I
.OwnerVer();
647 // Do it again and write it into the array
650 Res
= new Version
*[Size
+1];
663 // DepIterator::GlobOr - Compute an OR group /*{{{*/
664 // ---------------------------------------------------------------------
665 /* This Takes an iterator, iterates past the current dependency grouping
666 and returns Start and End so that so End is the final element
667 in the group, if End == Start then D is End++ and End is the
668 dependency D was pointing to. Use in loops to iterate sensibly. */
669 void pkgCache::DepIterator::GlobOr(DepIterator
&Start
,DepIterator
&End
)
671 // Compute a single dependency element (glob or)
674 for (bool LastOR
= true; end() == false && LastOR
== true;)
676 LastOR
= (S2
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
;
683 // DepIterator::IsIgnorable - should this packag/providr be ignored? /*{{{*/
684 // ---------------------------------------------------------------------
685 /* Deps like self-conflicts should be ignored as well as implicit conflicts
686 on virtual packages. */
687 bool pkgCache::DepIterator::IsIgnorable(PkgIterator
const &PT
) const
689 if (IsNegative() == false)
692 pkgCache::PkgIterator
const PP
= ParentPkg();
693 if (PP
->Group
!= PT
->Group
)
698 pkgCache::VerIterator
const PV
= ParentVer();
699 // ignore group-conflict on a M-A:same package - but not our implicit dependencies
700 // so that we can have M-A:same packages conflicting with their own real name
701 if ((PV
->MultiArch
& pkgCache::Version::Same
) == pkgCache::Version::Same
)
702 return IsMultiArchImplicit() == false;
706 bool pkgCache::DepIterator::IsIgnorable(PrvIterator
const &Prv
) const
708 if (IsNegative() == false)
711 PkgIterator
const Pkg
= ParentPkg();
712 /* Provides may never be applied against the same package (or group)
713 if it is a conflicts. See the comment above. */
714 if (Prv
.OwnerPkg()->Group
== Pkg
->Group
)
716 // Implicit group-conflicts should not be applied on providers of other groups
717 if (IsMultiArchImplicit() && Prv
.OwnerPkg()->Group
!= Pkg
->Group
)
723 // DepIterator::IsSatisfied - check if a version satisfied the dependency /*{{{*/
724 bool pkgCache::DepIterator::IsSatisfied(VerIterator
const &Ver
) const
726 return Owner
->VS
->CheckDep(Ver
.VerStr(),S2
->CompareOp
,TargetVer());
728 bool pkgCache::DepIterator::IsSatisfied(PrvIterator
const &Prv
) const
730 return Owner
->VS
->CheckDep(Prv
.ProvideVersion(),S2
->CompareOp
,TargetVer());
733 // DepIterator::IsImplicit - added by the cache generation /*{{{*/
734 bool pkgCache::DepIterator::IsImplicit() const
736 if (IsMultiArchImplicit() == true)
738 if (IsNegative() || S2
->Type
== pkgCache::Dep::Replaces
)
740 if ((S2
->CompareOp
& pkgCache::Dep::ArchSpecific
) != pkgCache::Dep::ArchSpecific
&&
741 strcmp(ParentPkg().Arch(), TargetPkg().Arch()) != 0)
747 // ostream operator to handle string representation of a dependecy /*{{{*/
748 // ---------------------------------------------------------------------
750 std::ostream
& operator<<(std::ostream
& out
, pkgCache::DepIterator D
)
753 return out
<< "invalid dependency";
755 pkgCache::PkgIterator P
= D
.ParentPkg();
756 pkgCache::PkgIterator T
= D
.TargetPkg();
758 out
<< (P
.end() ? "invalid pkg" : P
.FullName(false)) << " " << D
.DepType()
761 out
<< "invalid pkg";
766 out
<< " (" << D
.CompType() << " " << D
.TargetVer() << ")";
771 // VerIterator::CompareVer - Fast version compare for same pkgs /*{{{*/
772 // ---------------------------------------------------------------------
773 /* This just looks over the version list to see if B is listed before A. In
774 most cases this will return in under 4 checks, ver lists are short. */
775 int pkgCache::VerIterator::CompareVer(const VerIterator
&B
) const
777 // Check if they are equal
785 /* Start at A and look for B. If B is found then A > B otherwise
786 B was before A so A < B */
787 VerIterator I
= *this;
788 for (;I
.end() == false; ++I
)
794 // VerIterator::Downloadable - Checks if the version is downloadable /*{{{*/
795 // ---------------------------------------------------------------------
797 APT_PURE
bool pkgCache::VerIterator::Downloadable() const
799 VerFileIterator Files
= FileList();
800 for (; Files
.end() == false; ++Files
)
801 if (Files
.File().Flagged(pkgCache::Flag::NotSource
) == false)
806 // VerIterator::Automatic - Check if this version is 'automatic' /*{{{*/
807 // ---------------------------------------------------------------------
808 /* This checks to see if any of the versions files are not NotAutomatic.
809 True if this version is selectable for automatic installation. */
810 APT_PURE
bool pkgCache::VerIterator::Automatic() const
812 VerFileIterator Files
= FileList();
813 for (; Files
.end() == false; ++Files
)
814 // Do not check ButAutomaticUpgrades here as it is kind of automatic…
815 if (Files
.File().Flagged(pkgCache::Flag::NotAutomatic
) == false)
820 // VerIterator::NewestFile - Return the newest file version relation /*{{{*/
821 // ---------------------------------------------------------------------
822 /* This looks at the version numbers associated with all of the sources
823 this version is in and returns the highest.*/
824 pkgCache::VerFileIterator
pkgCache::VerIterator::NewestFile() const
826 VerFileIterator Files
= FileList();
827 VerFileIterator Highest
= Files
;
828 for (; Files
.end() == false; ++Files
)
830 if (Owner
->VS
->CmpReleaseVer(Files
.File().Version(),Highest
.File().Version()) > 0)
837 // VerIterator::RelStr - Release description string /*{{{*/
838 // ---------------------------------------------------------------------
839 /* This describes the version from a release-centric manner. The output is a
840 list of Label:Version/Archive */
841 static std::string
PkgFileIteratorToRelString(pkgCache::PkgFileIterator
const &File
)
844 if (File
.Label() != 0)
845 Res
= Res
+ File
.Label() + ':';
847 if (File
.Archive() != 0)
849 if (File
.Version() == 0)
850 Res
+= File
.Archive();
852 Res
= Res
+ File
.Version() + '/' + File
.Archive();
856 // No release file, print the host name that this came from
857 if (File
.Site() == 0 || File
.Site()[0] == 0)
864 string
pkgCache::VerIterator::RelStr() const
866 std::vector
<std::string
> RelStrs
;
867 for (pkgCache::VerFileIterator I
= this->FileList(); I
.end() == false; ++I
)
869 // Do not print 'not source' entries'
870 pkgCache::PkgFileIterator
const File
= I
.File();
871 if (File
.Flagged(pkgCache::Flag::NotSource
))
874 std::string
const RS
= PkgFileIteratorToRelString(File
);
875 if (std::find(RelStrs
.begin(), RelStrs
.end(), RS
) != RelStrs
.end())
878 RelStrs
.push_back(RS
);
880 std::ostringstream os
;
881 if (likely(RelStrs
.empty() == false))
883 std::copy(RelStrs
.begin(), RelStrs
.end()-1, std::ostream_iterator
<std::string
>(os
, ", "));
884 os
<< *RelStrs
.rbegin();
886 if (S
->ParentPkg
!= 0)
887 os
<< " [" << Arch() << "]";
891 // VerIterator::MultiArchType - string representing MultiArch flag /*{{{*/
892 const char * pkgCache::VerIterator::MultiArchType() const
894 if ((S
->MultiArch
& pkgCache::Version::Same
) == pkgCache::Version::Same
)
896 else if ((S
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
)
898 else if ((S
->MultiArch
& pkgCache::Version::Allowed
) == pkgCache::Version::Allowed
)
903 // RlsFileIterator::IsOk - Checks if the cache is in sync with the file /*{{{*/
904 // ---------------------------------------------------------------------
905 /* This stats the file and compares its stats with the ones that were
906 stored during generation. Date checks should probably also be
908 bool pkgCache::RlsFileIterator::IsOk()
911 if (stat(FileName(),&Buf
) != 0)
914 if (Buf
.st_size
!= (signed)S
->Size
|| Buf
.st_mtime
!= S
->mtime
)
920 // RlsFileIterator::RelStr - Return the release string /*{{{*/
921 string
pkgCache::RlsFileIterator::RelStr()
925 Res
= Res
+ (Res
.empty() == true?"v=":",v=") + Version();
927 Res
= Res
+ (Res
.empty() == true?"o=":",o=") + Origin();
929 Res
= Res
+ (Res
.empty() == true?"a=":",a=") + Archive();
931 Res
= Res
+ (Res
.empty() == true?"n=":",n=") + Codename();
933 Res
= Res
+ (Res
.empty() == true?"l=":",l=") + Label();
937 // PkgFileIterator::IsOk - Checks if the cache is in sync with the file /*{{{*/
938 // ---------------------------------------------------------------------
939 /* This stats the file and compares its stats with the ones that were
940 stored during generation. Date checks should probably also be
942 bool pkgCache::PkgFileIterator::IsOk()
945 if (stat(FileName(),&Buf
) != 0)
948 if (Buf
.st_size
!= (signed)S
->Size
|| Buf
.st_mtime
!= S
->mtime
)
954 string
pkgCache::PkgFileIterator::RelStr() /*{{{*/
957 if (ReleaseFile() == 0)
959 if (Component() != 0)
960 Res
= Res
+ (Res
.empty() == true?"a=":",a=") + Component();
964 Res
= ReleaseFile().RelStr();
965 if (Component() != 0)
966 Res
= Res
+ (Res
.empty() == true?"c=":",c=") + Component();
968 if (Architecture() != 0)
969 Res
= Res
+ (Res
.empty() == true?"b=":",b=") + Architecture();
973 // VerIterator::TranslatedDescription - Return the a DescIter for locale/*{{{*/
974 // ---------------------------------------------------------------------
975 /* return a DescIter for the current locale or the default if none is
978 pkgCache::DescIterator
pkgCache::VerIterator::TranslatedDescription() const
980 std::vector
<string
> const lang
= APT::Configuration::getLanguages();
981 for (std::vector
<string
>::const_iterator l
= lang
.begin();
982 l
!= lang
.end(); ++l
)
984 pkgCache::DescIterator Desc
= DescriptionList();
985 for (; Desc
.end() == false; ++Desc
)
986 if (*l
== Desc
.LanguageCode())
988 if (Desc
.end() == true)
992 Desc
= DescriptionList();
993 for (; Desc
.end() == false; ++Desc
)
994 if (strcmp(Desc
.LanguageCode(), "") == 0)
996 if (Desc
.end() == true)
1004 for (pkgCache::DescIterator Desc
= DescriptionList();
1005 Desc
.end() == false; ++Desc
)
1006 if (strcmp(Desc
.LanguageCode(), "") == 0)
1008 return DescriptionList();
1013 pkgCache::~pkgCache() {}