]> git.saurik.com Git - apt.git/blob - apt-pkg/pkgcache.cc
Switch to DJB hashing and use prime number as table size
[apt.git] / apt-pkg / pkgcache.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: pkgcache.cc,v 1.37 2003/02/10 01:40:58 doogie Exp $
4 /* ######################################################################
5
6 Package Cache - Accessor code for the cache
7
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!!
10
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.
16
17 The main class provides for ways to get package indexes and some
18 general lookup functions to start the iterators.
19
20 ##################################################################### */
21 /*}}}*/
22 // Include Files /*{{{*/
23 #include<config.h>
24
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>
34
35 #include <stddef.h>
36 #include <string.h>
37 #include <sstream>
38 #include <algorithm>
39 #include <vector>
40 #include <string>
41 #include <sys/stat.h>
42
43 #include <apti18n.h>
44 /*}}}*/
45
46 using std::string;
47
48
49 // Cache::Header::Header - Constructor /*{{{*/
50 // ---------------------------------------------------------------------
51 /* Simply initialize the header */
52 pkgCache::Header::Header()
53 {
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);
56
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);
62
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));
75 #undef APT_HEADER_SET
76
77 GroupCount = 0;
78 PackageCount = 0;
79 VersionCount = 0;
80 DescriptionCount = 0;
81 DependsCount = 0;
82 DependsDataCount = 0;
83 ReleaseFileCount = 0;
84 PackageFileCount = 0;
85 VerFileCount = 0;
86 DescFileCount = 0;
87 ProvidesCount = 0;
88 MaxVerFileSize = 0;
89 MaxDescFileSize = 0;
90
91 FileList = 0;
92 RlsFileList = 0;
93 VerSysName = 0;
94 Architecture = 0;
95 SetArchitectures(0);
96 SetHashTableSize(_config->FindI("APT::Cache-HashTableSize", 15013));
97 memset(Pools,0,sizeof(Pools));
98
99 CacheFileSize = 0;
100 }
101 /*}}}*/
102 // Cache::Header::CheckSizes - Check if the two headers have same *sz /*{{{*/
103 // ---------------------------------------------------------------------
104 /* */
105 bool pkgCache::Header::CheckSizes(Header &Against) const
106 {
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)
119 return true;
120 return false;
121 }
122 /*}}}*/
123
124 // Cache::pkgCache - Constructor /*{{{*/
125 // ---------------------------------------------------------------------
126 /* */
127 APT_IGNORE_DEPRECATED_PUSH
128 pkgCache::pkgCache(MMap *Map, bool DoMap) : Map(*Map), d(NULL)
129 {
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;
134 if (DoMap == true)
135 ReMap();
136 }
137 APT_IGNORE_DEPRECATED_POP
138 /*}}}*/
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)
143 {
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();
158
159 if (Errorchecks == false)
160 return true;
161
162 if (Map.Size() == 0 || HeaderP == 0)
163 return _error->Error(_("Empty package cache"));
164
165 // Check the header
166 Header DefHeader;
167 if (HeaderP->Signature != DefHeader.Signature ||
168 HeaderP->Dirty == true)
169 return _error->Error(_("The package cache file is corrupted"));
170
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"));
175
176 if (Map.Size() < HeaderP->CacheFileSize)
177 return _error->Error(_("The package cache file is corrupted, it is too small"));
178
179 if (HeaderP->VerSysName == 0 || HeaderP->Architecture == 0 || HeaderP->GetArchitectures() == 0)
180 return _error->Error(_("The package cache file is corrupted"));
181
182 // Locate our VS..
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);
185
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());
195
196 return true;
197 }
198 /*}}}*/
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
205 {
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();
210 }
211
212 map_id_t pkgCache::sHash(const char *Str) const
213 {
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();
218 }
219 /*}}}*/
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") */
231 if (Arch == "any")
232 return FindPkg(Name, "any");
233 return FindPkg(Name.substr(0, found), Arch);
234 }
235 /*}}}*/
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);
246
247 return Grp.FindPkg(Arch);
248 }
249 /*}}}*/
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);
256
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);
261 if (cmp == 0)
262 return GrpIterator(*this, Grp);
263 else if (cmp < 0)
264 break;
265 }
266
267 return GrpIterator(*this,0);
268 }
269 /*}}}*/
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)
275 {
276 const char * const Ops[] = {"","<=",">=","<<",">>","=","!="};
277 if (unlikely((unsigned)(Comp & 0xF) >= sizeof(Ops)/sizeof(Ops[0])))
278 return "";
279 return Ops[Comp & 0xF];
280 }
281 /*}}}*/
282 // Cache::CompType - Return a string describing the compare type /*{{{*/
283 // ---------------------------------------------------------------------
284 /* This returns a string representation of the dependency compare
285 type */
286 const char *pkgCache::CompType(unsigned char Comp)
287 {
288 const char * const Ops[] = {"","<=",">=","<",">","=","!="};
289 if (unlikely((unsigned)(Comp & 0xF) >= sizeof(Ops)/sizeof(Ops[0])))
290 return "";
291 return Ops[Comp & 0xF];
292 }
293 /*}}}*/
294 // Cache::DepType - Return a string describing the dep type /*{{{*/
295 // ---------------------------------------------------------------------
296 /* */
297 const char *pkgCache::DepType(unsigned char Type)
298 {
299 const char *Types[] = {"",_("Depends"),_("PreDepends"),_("Suggests"),
300 _("Recommends"),_("Conflicts"),_("Replaces"),
301 _("Obsoletes"),_("Breaks"), _("Enhances")};
302 if (Type < sizeof(Types)/sizeof(*Types))
303 return Types[Type];
304 return "";
305 }
306 /*}}}*/
307 // Cache::Priority - Convert a priority value to a string /*{{{*/
308 // ---------------------------------------------------------------------
309 /* */
310 const char *pkgCache::Priority(unsigned char Prio)
311 {
312 const char *Mapping[] = {0,_("required"),_("important"),_("standard"),
313 _("optional"),_("extra")};
314 if (Prio < _count(Mapping))
315 return Mapping[Prio];
316 return 0;
317 }
318 /*}}}*/
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);
325
326 /* If we accept any package we simply return the "first"
327 package in this group */
328 if (Arch == "any")
329 return PkgIterator(*Owner, Owner->PkgP + S->FirstPackage);
330 if (Arch == "native" || Arch == "all")
331 Arch = Owner->NativeArch();
332
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)
339 break;
340 }
341
342 return PkgIterator(*Owner, 0);
343 }
344 /*}}}*/
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))
351 return Pkg;
352
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) {
356 Pkg = FindPkg(*a);
357 if (Pkg.end() == false && (PreferNonVirtual == false || Pkg->VersionList != 0))
358 return Pkg;
359 }
360 // packages without an architecture
361 Pkg = FindPkg("none");
362 if (Pkg.end() == false && (PreferNonVirtual == false || Pkg->VersionList != 0))
363 return Pkg;
364
365 if (PreferNonVirtual == true)
366 return FindPreferredPkg(false);
367 return PkgIterator(*Owner, 0);
368 }
369 /*}}}*/
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);
379
380 if (S->LastPackage == LastPkg.Index())
381 return PkgIterator(*Owner, 0);
382
383 return PkgIterator(*Owner, Owner->PkgP + LastPkg->NextPackage);
384 }
385 /*}}}*/
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++()
390 {
391 // Follow the current links
392 if (S != Owner->GrpP)
393 S = Owner->GrpP + S->Next;
394
395 // Follow the hash table
396 while (S == Owner->GrpP && (HashIndex+1) < (signed)Owner->HeaderP->GetHashTableSize())
397 {
398 ++HashIndex;
399 S = Owner->GrpP + Owner->HeaderP->GrpHashTableP()[HashIndex];
400 }
401 return *this;
402 }
403 /*}}}*/
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++()
408 {
409 // Follow the current links
410 if (S != Owner->PkgP)
411 S = Owner->PkgP + S->NextPackage;
412
413 // Follow the hash table
414 while (S == Owner->PkgP && (HashIndex+1) < (signed)Owner->HeaderP->GetHashTableSize())
415 {
416 ++HashIndex;
417 S = Owner->PkgP + Owner->HeaderP->PkgHashTableP()[HashIndex];
418 }
419 return *this;
420 }
421 /*}}}*/
422 pkgCache::DepIterator& pkgCache::DepIterator::operator++() /*{{{*/
423 {
424 if (S == Owner->DepP)
425 return *this;
426 S = Owner->DepP + (Type == DepVer ? S->NextDepends : S->NextRevDepends);
427 if (S == Owner->DepP)
428 S2 = Owner->DepDataP;
429 else
430 S2 = Owner->DepDataP + S->DependencyData;
431 return *this;
432 }
433 /*}}}*/
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
438 {
439 if (S->InstState == pkgCache::State::ReInstReq ||
440 S->InstState == pkgCache::State::HoldReInstReq)
441 return NeedsUnpack;
442
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;
452
453 if (S->CurrentState == pkgCache::State::HalfInstalled ||
454 S->InstState != pkgCache::State::Ok)
455 return NeedsUnpack;
456
457 return NeedsNothing;
458 }
459 /*}}}*/
460 // PkgIterator::CandVersion - Returns the candidate version string /*{{{*/
461 // ---------------------------------------------------------------------
462 /* Return string representing of the candidate version. */
463 const char *
464 pkgCache::PkgIterator::CandVersion() const
465 {
466 //TargetVer is empty, so don't use it.
467 VerIterator version = pkgPolicy(Owner).GetCandidateVer(*this);
468 if (version.IsGood())
469 return version.VerStr();
470 return 0;
471 }
472 /*}}}*/
473 // PkgIterator::CurVersion - Returns the current version string /*{{{*/
474 // ---------------------------------------------------------------------
475 /* Return string representing of the current version. */
476 const char *
477 pkgCache::PkgIterator::CurVersion() const
478 {
479 VerIterator version = CurrentVer();
480 if (version.IsGood())
481 return CurrentVer().VerStr();
482 return 0;
483 }
484 /*}}}*/
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. */
491 std::ostream&
492 operator<<(std::ostream& out, pkgCache::PkgIterator Pkg)
493 {
494 if (Pkg.end() == true)
495 return out << "invalid package";
496
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());
500
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 )";
508 else
509 out << " > ( " << string(Pkg.VersionList().Section()==0?"unknown":Pkg.VersionList().Section()) << " )";
510 return out;
511 }
512 /*}}}*/
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
517 {
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());
523 return fullname;
524 }
525 /*}}}*/
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
531 {
532 if (IsNegative() == true ||
533 S2->Type == pkgCache::Dep::Depends ||
534 S2->Type == pkgCache::Dep::PreDepends)
535 return true;
536 return false;
537 }
538 /*}}}*/
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
544 {
545 return S2->Type == Dep::DpkgBreaks ||
546 S2->Type == Dep::Conflicts ||
547 S2->Type == Dep::Obsoletes;
548 }
549 /*}}}*/
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
559
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
564 {
565 Result = TargetPkg();
566
567 // No provides at all
568 if (Result->ProvidesList == 0)
569 return false;
570
571 // There is the Base package and the providing ones which is at least 2
572 if (Result->VersionList != 0)
573 return true;
574
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);
581
582 // Nothing but indirect self provides
583 if (PStart.end() == true)
584 return false;
585
586 // Check for single packages in the provides list
587 PrvIterator P = PStart;
588 for (; P.end() != true; ++P)
589 {
590 // Skip over self provides
591 if (P.OwnerPkg() == ParentPkg())
592 continue;
593 if (PStart.OwnerPkg() != P.OwnerPkg())
594 break;
595 }
596
597 Result = PStart.OwnerPkg();
598
599 // Check for non dups
600 if (P.end() != true)
601 return true;
602
603 return false;
604 }
605 /*}}}*/
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
613 {
614 Version **Res = 0;
615 unsigned long Size =0;
616 while (1)
617 {
618 Version **End = Res;
619 PkgIterator DPkg = TargetPkg();
620
621 // Walk along the actual package providing versions
622 for (VerIterator I = DPkg.VersionList(); I.end() == false; ++I)
623 {
624 if (IsIgnorable(I.ParentPkg()) == true)
625 continue;
626 if (IsSatisfied(I) == false)
627 continue;
628
629 Size++;
630 if (Res != 0)
631 *End++ = I;
632 }
633
634 // Follow all provides
635 for (PrvIterator I = DPkg.ProvidesList(); I.end() == false; ++I)
636 {
637 if (IsIgnorable(I) == true)
638 continue;
639 if (IsSatisfied(I) == false)
640 continue;
641
642 Size++;
643 if (Res != 0)
644 *End++ = I.OwnerVer();
645 }
646
647 // Do it again and write it into the array
648 if (Res == 0)
649 {
650 Res = new Version *[Size+1];
651 Size = 0;
652 }
653 else
654 {
655 *End = 0;
656 break;
657 }
658 }
659
660 return Res;
661 }
662 /*}}}*/
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)
670 {
671 // Compute a single dependency element (glob or)
672 Start = *this;
673 End = *this;
674 for (bool LastOR = true; end() == false && LastOR == true;)
675 {
676 LastOR = (S2->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or;
677 ++(*this);
678 if (LastOR == true)
679 End = (*this);
680 }
681 }
682 /*}}}*/
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
688 {
689 if (IsNegative() == false)
690 return false;
691
692 pkgCache::PkgIterator const PP = ParentPkg();
693 if (PP->Group != PT->Group)
694 return false;
695 // self-conflict
696 if (PP == PT)
697 return true;
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;
703
704 return false;
705 }
706 bool pkgCache::DepIterator::IsIgnorable(PrvIterator const &Prv) const
707 {
708 if (IsNegative() == false)
709 return false;
710
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)
715 return true;
716 // Implicit group-conflicts should not be applied on providers of other groups
717 if (IsMultiArchImplicit() && Prv.OwnerPkg()->Group != Pkg->Group)
718 return true;
719
720 return false;
721 }
722 /*}}}*/
723 // DepIterator::IsSatisfied - check if a version satisfied the dependency /*{{{*/
724 bool pkgCache::DepIterator::IsSatisfied(VerIterator const &Ver) const
725 {
726 return Owner->VS->CheckDep(Ver.VerStr(),S2->CompareOp,TargetVer());
727 }
728 bool pkgCache::DepIterator::IsSatisfied(PrvIterator const &Prv) const
729 {
730 return Owner->VS->CheckDep(Prv.ProvideVersion(),S2->CompareOp,TargetVer());
731 }
732 /*}}}*/
733 // DepIterator::IsImplicit - added by the cache generation /*{{{*/
734 bool pkgCache::DepIterator::IsImplicit() const
735 {
736 if (IsMultiArchImplicit() == true)
737 return true;
738 if (IsNegative() || S2->Type == pkgCache::Dep::Replaces)
739 {
740 if ((S2->CompareOp & pkgCache::Dep::ArchSpecific) != pkgCache::Dep::ArchSpecific &&
741 strcmp(ParentPkg().Arch(), TargetPkg().Arch()) != 0)
742 return true;
743 }
744 return false;
745 }
746 /*}}}*/
747 // ostream operator to handle string representation of a dependecy /*{{{*/
748 // ---------------------------------------------------------------------
749 /* */
750 std::ostream& operator<<(std::ostream& out, pkgCache::DepIterator D)
751 {
752 if (D.end() == true)
753 return out << "invalid dependency";
754
755 pkgCache::PkgIterator P = D.ParentPkg();
756 pkgCache::PkgIterator T = D.TargetPkg();
757
758 out << (P.end() ? "invalid pkg" : P.FullName(false)) << " " << D.DepType()
759 << " on ";
760 if (T.end() == true)
761 out << "invalid pkg";
762 else
763 out << T;
764
765 if (D->Version != 0)
766 out << " (" << D.CompType() << " " << D.TargetVer() << ")";
767
768 return out;
769 }
770 /*}}}*/
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
776 {
777 // Check if they are equal
778 if (*this == B)
779 return 0;
780 if (end() == true)
781 return -1;
782 if (B.end() == true)
783 return 1;
784
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)
789 if (I == B)
790 return 1;
791 return -1;
792 }
793 /*}}}*/
794 // VerIterator::Downloadable - Checks if the version is downloadable /*{{{*/
795 // ---------------------------------------------------------------------
796 /* */
797 APT_PURE bool pkgCache::VerIterator::Downloadable() const
798 {
799 VerFileIterator Files = FileList();
800 for (; Files.end() == false; ++Files)
801 if (Files.File().Flagged(pkgCache::Flag::NotSource) == false)
802 return true;
803 return false;
804 }
805 /*}}}*/
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
811 {
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)
816 return true;
817 return false;
818 }
819 /*}}}*/
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
825 {
826 VerFileIterator Files = FileList();
827 VerFileIterator Highest = Files;
828 for (; Files.end() == false; ++Files)
829 {
830 if (Owner->VS->CmpReleaseVer(Files.File().Version(),Highest.File().Version()) > 0)
831 Highest = Files;
832 }
833
834 return Highest;
835 }
836 /*}}}*/
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)
842 {
843 std::string Res;
844 if (File.Label() != 0)
845 Res = Res + File.Label() + ':';
846
847 if (File.Archive() != 0)
848 {
849 if (File.Version() == 0)
850 Res += File.Archive();
851 else
852 Res = Res + File.Version() + '/' + File.Archive();
853 }
854 else
855 {
856 // No release file, print the host name that this came from
857 if (File.Site() == 0 || File.Site()[0] == 0)
858 Res += "localhost";
859 else
860 Res += File.Site();
861 }
862 return Res;
863 }
864 string pkgCache::VerIterator::RelStr() const
865 {
866 std::vector<std::string> RelStrs;
867 for (pkgCache::VerFileIterator I = this->FileList(); I.end() == false; ++I)
868 {
869 // Do not print 'not source' entries'
870 pkgCache::PkgFileIterator const File = I.File();
871 if (File.Flagged(pkgCache::Flag::NotSource))
872 continue;
873
874 std::string const RS = PkgFileIteratorToRelString(File);
875 if (std::find(RelStrs.begin(), RelStrs.end(), RS) != RelStrs.end())
876 continue;
877
878 RelStrs.push_back(RS);
879 }
880 std::ostringstream os;
881 if (likely(RelStrs.empty() == false))
882 {
883 std::copy(RelStrs.begin(), RelStrs.end()-1, std::ostream_iterator<std::string>(os, ", "));
884 os << *RelStrs.rbegin();
885 }
886 if (S->ParentPkg != 0)
887 os << " [" << Arch() << "]";
888 return os.str();
889 }
890 /*}}}*/
891 // VerIterator::MultiArchType - string representing MultiArch flag /*{{{*/
892 const char * pkgCache::VerIterator::MultiArchType() const
893 {
894 if ((S->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same)
895 return "same";
896 else if ((S->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign)
897 return "foreign";
898 else if ((S->MultiArch & pkgCache::Version::Allowed) == pkgCache::Version::Allowed)
899 return "allowed";
900 return "none";
901 }
902 /*}}}*/
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
907 included here. */
908 bool pkgCache::RlsFileIterator::IsOk()
909 {
910 struct stat Buf;
911 if (stat(FileName(),&Buf) != 0)
912 return false;
913
914 if (Buf.st_size != (signed)S->Size || Buf.st_mtime != S->mtime)
915 return false;
916
917 return true;
918 }
919 /*}}}*/
920 // RlsFileIterator::RelStr - Return the release string /*{{{*/
921 string pkgCache::RlsFileIterator::RelStr()
922 {
923 string Res;
924 if (Version() != 0)
925 Res = Res + (Res.empty() == true?"v=":",v=") + Version();
926 if (Origin() != 0)
927 Res = Res + (Res.empty() == true?"o=":",o=") + Origin();
928 if (Archive() != 0)
929 Res = Res + (Res.empty() == true?"a=":",a=") + Archive();
930 if (Codename() != 0)
931 Res = Res + (Res.empty() == true?"n=":",n=") + Codename();
932 if (Label() != 0)
933 Res = Res + (Res.empty() == true?"l=":",l=") + Label();
934 return Res;
935 }
936 /*}}}*/
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
941 included here. */
942 bool pkgCache::PkgFileIterator::IsOk()
943 {
944 struct stat Buf;
945 if (stat(FileName(),&Buf) != 0)
946 return false;
947
948 if (Buf.st_size != (signed)S->Size || Buf.st_mtime != S->mtime)
949 return false;
950
951 return true;
952 }
953 /*}}}*/
954 string pkgCache::PkgFileIterator::RelStr() /*{{{*/
955 {
956 std::string Res;
957 if (ReleaseFile() == 0)
958 {
959 if (Component() != 0)
960 Res = Res + (Res.empty() == true?"a=":",a=") + Component();
961 }
962 else
963 {
964 Res = ReleaseFile().RelStr();
965 if (Component() != 0)
966 Res = Res + (Res.empty() == true?"c=":",c=") + Component();
967 }
968 if (Architecture() != 0)
969 Res = Res + (Res.empty() == true?"b=":",b=") + Architecture();
970 return Res;
971 }
972 /*}}}*/
973 // VerIterator::TranslatedDescription - Return the a DescIter for locale/*{{{*/
974 // ---------------------------------------------------------------------
975 /* return a DescIter for the current locale or the default if none is
976 * found
977 */
978 pkgCache::DescIterator pkgCache::VerIterator::TranslatedDescription() const
979 {
980 std::vector<string> const lang = APT::Configuration::getLanguages();
981 for (std::vector<string>::const_iterator l = lang.begin();
982 l != lang.end(); ++l)
983 {
984 pkgCache::DescIterator Desc = DescriptionList();
985 for (; Desc.end() == false; ++Desc)
986 if (*l == Desc.LanguageCode())
987 break;
988 if (Desc.end() == true)
989 {
990 if (*l == "en")
991 {
992 Desc = DescriptionList();
993 for (; Desc.end() == false; ++Desc)
994 if (strcmp(Desc.LanguageCode(), "") == 0)
995 break;
996 if (Desc.end() == true)
997 continue;
998 }
999 else
1000 continue;
1001 }
1002 return Desc;
1003 }
1004 for (pkgCache::DescIterator Desc = DescriptionList();
1005 Desc.end() == false; ++Desc)
1006 if (strcmp(Desc.LanguageCode(), "") == 0)
1007 return Desc;
1008 return DescriptionList();
1009 }
1010
1011 /*}}}*/
1012
1013 pkgCache::~pkgCache() {}