]> git.saurik.com Git - apt.git/blob - apt-pkg/pkgcache.cc
Merge remote-tracking branch 'mvo/feature/hash-stats' into debian/experimental
[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 <ostream>
38 #include <vector>
39 #include <string>
40 #include <sys/stat.h>
41
42 #include <apti18n.h>
43 /*}}}*/
44
45 using std::string;
46
47
48 // Cache::Header::Header - Constructor /*{{{*/
49 // ---------------------------------------------------------------------
50 /* Simply initialize the header */
51 pkgCache::Header::Header()
52 {
53 Signature = 0x98FE76DC;
54
55 /* Whenever the structures change the major version should be bumped,
56 whenever the generator changes the minor version should be bumped. */
57 MajorVersion = 9;
58 MinorVersion = 2;
59 Dirty = false;
60
61 HeaderSz = sizeof(pkgCache::Header);
62 GroupSz = sizeof(pkgCache::Group);
63 PackageSz = sizeof(pkgCache::Package);
64 PackageFileSz = sizeof(pkgCache::PackageFile);
65 VersionSz = sizeof(pkgCache::Version);
66 DescriptionSz = sizeof(pkgCache::Description);
67 DependencySz = sizeof(pkgCache::Dependency);
68 ProvidesSz = sizeof(pkgCache::Provides);
69 VerFileSz = sizeof(pkgCache::VerFile);
70 DescFileSz = sizeof(pkgCache::DescFile);
71
72 GroupCount = 0;
73 PackageCount = 0;
74 VersionCount = 0;
75 DescriptionCount = 0;
76 DependsCount = 0;
77 PackageFileCount = 0;
78 VerFileCount = 0;
79 DescFileCount = 0;
80 ProvidesCount = 0;
81 MaxVerFileSize = 0;
82 MaxDescFileSize = 0;
83
84 FileList = 0;
85 StringList = 0;
86 VerSysName = 0;
87 Architecture = 0;
88 memset(PkgHashTable,0,sizeof(PkgHashTable));
89 memset(GrpHashTable,0,sizeof(GrpHashTable));
90 memset(Pools,0,sizeof(Pools));
91
92 CacheFileSize = 0;
93 }
94 /*}}}*/
95 // Cache::Header::CheckSizes - Check if the two headers have same *sz /*{{{*/
96 // ---------------------------------------------------------------------
97 /* */
98 bool pkgCache::Header::CheckSizes(Header &Against) const
99 {
100 if (HeaderSz == Against.HeaderSz &&
101 GroupSz == Against.GroupSz &&
102 PackageSz == Against.PackageSz &&
103 PackageFileSz == Against.PackageFileSz &&
104 VersionSz == Against.VersionSz &&
105 DescriptionSz == Against.DescriptionSz &&
106 DependencySz == Against.DependencySz &&
107 VerFileSz == Against.VerFileSz &&
108 DescFileSz == Against.DescFileSz &&
109 ProvidesSz == Against.ProvidesSz)
110 return true;
111 return false;
112 }
113 /*}}}*/
114
115 // Cache::pkgCache - Constructor /*{{{*/
116 // ---------------------------------------------------------------------
117 /* */
118 pkgCache::pkgCache(MMap *Map, bool DoMap) : Map(*Map)
119 {
120 // call getArchitectures() with cached=false to ensure that the
121 // architectures cache is re-evaulated. this is needed in cases
122 // when the APT::Architecture field changes between two cache creations
123 MultiArchEnabled = APT::Configuration::getArchitectures(false).size() > 1;
124 if (DoMap == true)
125 ReMap();
126 }
127 /*}}}*/
128 // Cache::ReMap - Reopen the cache file /*{{{*/
129 // ---------------------------------------------------------------------
130 /* If the file is already closed then this will open it open it. */
131 bool pkgCache::ReMap(bool const &Errorchecks)
132 {
133 // Apply the typecasts.
134 HeaderP = (Header *)Map.Data();
135 GrpP = (Group *)Map.Data();
136 PkgP = (Package *)Map.Data();
137 VerFileP = (VerFile *)Map.Data();
138 DescFileP = (DescFile *)Map.Data();
139 PkgFileP = (PackageFile *)Map.Data();
140 VerP = (Version *)Map.Data();
141 DescP = (Description *)Map.Data();
142 ProvideP = (Provides *)Map.Data();
143 DepP = (Dependency *)Map.Data();
144 StringItemP = (StringItem *)Map.Data();
145 StrP = (char *)Map.Data();
146
147 if (Errorchecks == false)
148 return true;
149
150 if (Map.Size() == 0 || HeaderP == 0)
151 return _error->Error(_("Empty package cache"));
152
153 // Check the header
154 Header DefHeader;
155 if (HeaderP->Signature != DefHeader.Signature ||
156 HeaderP->Dirty == true)
157 return _error->Error(_("The package cache file is corrupted"));
158
159 if (HeaderP->MajorVersion != DefHeader.MajorVersion ||
160 HeaderP->MinorVersion != DefHeader.MinorVersion ||
161 HeaderP->CheckSizes(DefHeader) == false)
162 return _error->Error(_("The package cache file is an incompatible version"));
163
164 if (Map.Size() < HeaderP->CacheFileSize)
165 return _error->Error(_("The package cache file is corrupted, it is too small"));
166
167 if (HeaderP->VerSysName == 0 || HeaderP->Architecture == 0 || HeaderP->Architectures == 0)
168 return _error->Error(_("The package cache file is corrupted"));
169
170 // Locate our VS..
171 if ((VS = pkgVersioningSystem::GetVS(StrP + HeaderP->VerSysName)) == 0)
172 return _error->Error(_("This APT does not support the versioning system '%s'"),StrP + HeaderP->VerSysName);
173
174 // Check the architecture
175 std::vector<std::string> archs = APT::Configuration::getArchitectures();
176 std::vector<std::string>::const_iterator a = archs.begin();
177 std::string list = *a;
178 for (++a; a != archs.end(); ++a)
179 list.append(",").append(*a);
180 if (_config->Find("APT::Architecture") != StrP + HeaderP->Architecture ||
181 list != StrP + HeaderP->Architectures)
182 return _error->Error(_("The package cache was built for different architectures: %s vs %s"), StrP + HeaderP->Architectures, list.c_str());
183
184 return true;
185 }
186 /*}}}*/
187 // Cache::Hash - Hash a string /*{{{*/
188 // ---------------------------------------------------------------------
189 /* This is used to generate the hash entries for the HashTable. With my
190 package list from bo this function gets 94% table usage on a 512 item
191 table (480 used items) */
192 unsigned long pkgCache::sHash(const string &Str) const
193 {
194 unsigned long Hash = 0;
195 for (string::const_iterator I = Str.begin(); I != Str.end(); ++I)
196 Hash = 41 * Hash + tolower_ascii(*I);
197 return Hash % _count(HeaderP->PkgHashTable);
198 }
199
200 unsigned long pkgCache::sHash(const char *Str) const
201 {
202 unsigned long Hash = tolower_ascii(*Str);
203 for (const char *I = Str + 1; *I != 0; ++I)
204 Hash = 41 * Hash + tolower_ascii(*I);
205 return Hash % _count(HeaderP->PkgHashTable);
206 }
207 /*}}}*/
208 // Cache::SingleArchFindPkg - Locate a package by name /*{{{*/
209 // ---------------------------------------------------------------------
210 /* Returns 0 on error, pointer to the package otherwise
211 The multiArch enabled methods will fallback to this one as it is (a bit)
212 faster for single arch environments and realworld is mostly singlearch… */
213 pkgCache::PkgIterator pkgCache::SingleArchFindPkg(const string &Name)
214 {
215 // Look at the hash bucket
216 Package *Pkg = PkgP + HeaderP->PkgHashTable[Hash(Name)];
217 for (; Pkg != PkgP; Pkg = PkgP + Pkg->Next)
218 {
219 if (unlikely(Pkg->Name == 0))
220 continue;
221
222 int const cmp = strcasecmp(Name.c_str(), StrP + Pkg->Name);
223 if (cmp == 0)
224 return PkgIterator(*this, Pkg);
225 else if (cmp < 0)
226 break;
227 }
228 return PkgIterator(*this,0);
229 }
230 /*}}}*/
231 // Cache::FindPkg - Locate a package by name /*{{{*/
232 // ---------------------------------------------------------------------
233 /* Returns 0 on error, pointer to the package otherwise */
234 pkgCache::PkgIterator pkgCache::FindPkg(const string &Name) {
235 size_t const found = Name.find(':');
236 if (found == string::npos)
237 {
238 if (MultiArchCache() == false)
239 return SingleArchFindPkg(Name);
240 else
241 return FindPkg(Name, "native");
242 }
243 string const Arch = Name.substr(found+1);
244 /* Beware: This is specialcased to handle pkg:any in dependencies as
245 these are linked to virtual pkg:any named packages with all archs.
246 If you want any arch from a given pkg, use FindPkg(pkg,arch) */
247 if (Arch == "any")
248 return FindPkg(Name, "any");
249 return FindPkg(Name.substr(0, found), Arch);
250 }
251 /*}}}*/
252 // Cache::FindPkg - Locate a package by name /*{{{*/
253 // ---------------------------------------------------------------------
254 /* Returns 0 on error, pointer to the package otherwise */
255 pkgCache::PkgIterator pkgCache::FindPkg(const string &Name, string const &Arch) {
256 if (MultiArchCache() == false && Arch != "none") {
257 if (Arch == "native" || Arch == "all" || Arch == "any" ||
258 Arch == NativeArch())
259 return SingleArchFindPkg(Name);
260 else
261 return PkgIterator(*this,0);
262 }
263 /* We make a detour via the GrpIterator here as
264 on a multi-arch environment a group is easier to
265 find than a package (less entries in the buckets) */
266 pkgCache::GrpIterator Grp = FindGrp(Name);
267 if (Grp.end() == true)
268 return PkgIterator(*this,0);
269
270 return Grp.FindPkg(Arch);
271 }
272 /*}}}*/
273 // Cache::FindGrp - Locate a group by name /*{{{*/
274 // ---------------------------------------------------------------------
275 /* Returns End-Pointer on error, pointer to the group otherwise */
276 pkgCache::GrpIterator pkgCache::FindGrp(const string &Name) {
277 if (unlikely(Name.empty() == true))
278 return GrpIterator(*this,0);
279
280 // Look at the hash bucket for the group
281 Group *Grp = GrpP + HeaderP->GrpHashTable[sHash(Name)];
282 for (; Grp != GrpP; Grp = GrpP + Grp->Next) {
283 if (unlikely(Grp->Name == 0))
284 continue;
285
286 int const cmp = strcasecmp(Name.c_str(), StrP + Grp->Name);
287 if (cmp == 0)
288 return GrpIterator(*this, Grp);
289 else if (cmp < 0)
290 break;
291 }
292
293 return GrpIterator(*this,0);
294 }
295 /*}}}*/
296 // Cache::CompTypeDeb - Return a string describing the compare type /*{{{*/
297 // ---------------------------------------------------------------------
298 /* This returns a string representation of the dependency compare
299 type in the weird debian style.. */
300 const char *pkgCache::CompTypeDeb(unsigned char Comp)
301 {
302 const char * const Ops[] = {"","<=",">=","<<",">>","=","!="};
303 if (unlikely((unsigned)(Comp & 0xF) >= sizeof(Ops)/sizeof(Ops[0])))
304 return "";
305 return Ops[Comp & 0xF];
306 }
307 /*}}}*/
308 // Cache::CompType - Return a string describing the compare type /*{{{*/
309 // ---------------------------------------------------------------------
310 /* This returns a string representation of the dependency compare
311 type */
312 const char *pkgCache::CompType(unsigned char Comp)
313 {
314 const char * const Ops[] = {"","<=",">=","<",">","=","!="};
315 if (unlikely((unsigned)(Comp & 0xF) >= sizeof(Ops)/sizeof(Ops[0])))
316 return "";
317 return Ops[Comp & 0xF];
318 }
319 /*}}}*/
320 // Cache::DepType - Return a string describing the dep type /*{{{*/
321 // ---------------------------------------------------------------------
322 /* */
323 const char *pkgCache::DepType(unsigned char Type)
324 {
325 const char *Types[] = {"",_("Depends"),_("PreDepends"),_("Suggests"),
326 _("Recommends"),_("Conflicts"),_("Replaces"),
327 _("Obsoletes"),_("Breaks"), _("Enhances")};
328 if (Type < sizeof(Types)/sizeof(*Types))
329 return Types[Type];
330 return "";
331 }
332 /*}}}*/
333 // Cache::Priority - Convert a priority value to a string /*{{{*/
334 // ---------------------------------------------------------------------
335 /* */
336 const char *pkgCache::Priority(unsigned char Prio)
337 {
338 const char *Mapping[] = {0,_("important"),_("required"),_("standard"),
339 _("optional"),_("extra")};
340 if (Prio < _count(Mapping))
341 return Mapping[Prio];
342 return 0;
343 }
344 /*}}}*/
345 // GrpIterator::FindPkg - Locate a package by arch /*{{{*/
346 // ---------------------------------------------------------------------
347 /* Returns an End-Pointer on error, pointer to the package otherwise */
348 pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) const {
349 if (unlikely(IsGood() == false || S->FirstPackage == 0))
350 return PkgIterator(*Owner, 0);
351
352 /* If we accept any package we simply return the "first"
353 package in this group (the last one added). */
354 if (Arch == "any")
355 return PkgIterator(*Owner, Owner->PkgP + S->FirstPackage);
356
357 char const* const myArch = Owner->NativeArch();
358 /* Most of the time the package for our native architecture is
359 the one we add at first to the cache, but this would be the
360 last one we check, so we do it now. */
361 if (Arch == "native" || Arch == myArch || Arch == "all") {
362 pkgCache::Package *Pkg = Owner->PkgP + S->LastPackage;
363 if (strcasecmp(myArch, Owner->StrP + Pkg->Arch) == 0)
364 return PkgIterator(*Owner, Pkg);
365 Arch = myArch;
366 }
367
368 /* Iterate over the list to find the matching arch
369 unfortunately this list includes "package noise"
370 (= different packages with same calculated hash),
371 so we need to check the name also */
372 for (pkgCache::Package *Pkg = PackageList(); Pkg != Owner->PkgP;
373 Pkg = Owner->PkgP + Pkg->Next) {
374 if (S->Name == Pkg->Name &&
375 stringcasecmp(Arch, Owner->StrP + Pkg->Arch) == 0)
376 return PkgIterator(*Owner, Pkg);
377 if ((Owner->PkgP + S->LastPackage) == Pkg)
378 break;
379 }
380
381 return PkgIterator(*Owner, 0);
382 }
383 /*}}}*/
384 // GrpIterator::FindPreferredPkg - Locate the "best" package /*{{{*/
385 // ---------------------------------------------------------------------
386 /* Returns an End-Pointer on error, pointer to the package otherwise */
387 pkgCache::PkgIterator pkgCache::GrpIterator::FindPreferredPkg(bool const &PreferNonVirtual) const {
388 pkgCache::PkgIterator Pkg = FindPkg("native");
389 if (Pkg.end() == false && (PreferNonVirtual == false || Pkg->VersionList != 0))
390 return Pkg;
391
392 std::vector<std::string> const archs = APT::Configuration::getArchitectures();
393 for (std::vector<std::string>::const_iterator a = archs.begin();
394 a != archs.end(); ++a) {
395 Pkg = FindPkg(*a);
396 if (Pkg.end() == false && (PreferNonVirtual == false || Pkg->VersionList != 0))
397 return Pkg;
398 }
399 // packages without an architecture
400 Pkg = FindPkg("none");
401 if (Pkg.end() == false && (PreferNonVirtual == false || Pkg->VersionList != 0))
402 return Pkg;
403
404 if (PreferNonVirtual == true)
405 return FindPreferredPkg(false);
406 return PkgIterator(*Owner, 0);
407 }
408 /*}}}*/
409 // GrpIterator::NextPkg - Locate the next package in the group /*{{{*/
410 // ---------------------------------------------------------------------
411 /* Returns an End-Pointer on error, pointer to the package otherwise.
412 We can't simply ++ to the next as the next package of the last will
413 be from a different group (with the same hash value) */
414 pkgCache::PkgIterator pkgCache::GrpIterator::NextPkg(pkgCache::PkgIterator const &LastPkg) const {
415 if (unlikely(IsGood() == false || S->FirstPackage == 0 ||
416 LastPkg.end() == true))
417 return PkgIterator(*Owner, 0);
418
419 if (S->LastPackage == LastPkg.Index())
420 return PkgIterator(*Owner, 0);
421
422 return PkgIterator(*Owner, Owner->PkgP + LastPkg->Next);
423 }
424 /*}}}*/
425 // GrpIterator::operator ++ - Postfix incr /*{{{*/
426 // ---------------------------------------------------------------------
427 /* This will advance to the next logical group in the hash table. */
428 void pkgCache::GrpIterator::operator ++(int)
429 {
430 // Follow the current links
431 if (S != Owner->GrpP)
432 S = Owner->GrpP + S->Next;
433
434 // Follow the hash table
435 while (S == Owner->GrpP && (HashIndex+1) < (signed)_count(Owner->HeaderP->GrpHashTable))
436 {
437 HashIndex++;
438 S = Owner->GrpP + Owner->HeaderP->GrpHashTable[HashIndex];
439 }
440 }
441 /*}}}*/
442 // PkgIterator::operator ++ - Postfix incr /*{{{*/
443 // ---------------------------------------------------------------------
444 /* This will advance to the next logical package in the hash table. */
445 void pkgCache::PkgIterator::operator ++(int)
446 {
447 // Follow the current links
448 if (S != Owner->PkgP)
449 S = Owner->PkgP + S->Next;
450
451 // Follow the hash table
452 while (S == Owner->PkgP && (HashIndex+1) < (signed)_count(Owner->HeaderP->PkgHashTable))
453 {
454 HashIndex++;
455 S = Owner->PkgP + Owner->HeaderP->PkgHashTable[HashIndex];
456 }
457 }
458 /*}}}*/
459 // PkgIterator::State - Check the State of the package /*{{{*/
460 // ---------------------------------------------------------------------
461 /* By this we mean if it is either cleanly installed or cleanly removed. */
462 pkgCache::PkgIterator::OkState pkgCache::PkgIterator::State() const
463 {
464 if (S->InstState == pkgCache::State::ReInstReq ||
465 S->InstState == pkgCache::State::HoldReInstReq)
466 return NeedsUnpack;
467
468 if (S->CurrentState == pkgCache::State::UnPacked ||
469 S->CurrentState == pkgCache::State::HalfConfigured)
470 // we leave triggers alone complettely. dpkg deals with
471 // them in a hard-to-predict manner and if they get
472 // resolved by dpkg before apt run dpkg --configure on
473 // the TriggersPending package dpkg returns a error
474 //Pkg->CurrentState == pkgCache::State::TriggersAwaited
475 //Pkg->CurrentState == pkgCache::State::TriggersPending)
476 return NeedsConfigure;
477
478 if (S->CurrentState == pkgCache::State::HalfInstalled ||
479 S->InstState != pkgCache::State::Ok)
480 return NeedsUnpack;
481
482 return NeedsNothing;
483 }
484 /*}}}*/
485 // PkgIterator::CandVersion - Returns the candidate version string /*{{{*/
486 // ---------------------------------------------------------------------
487 /* Return string representing of the candidate version. */
488 const char *
489 pkgCache::PkgIterator::CandVersion() const
490 {
491 //TargetVer is empty, so don't use it.
492 VerIterator version = pkgPolicy(Owner).GetCandidateVer(*this);
493 if (version.IsGood())
494 return version.VerStr();
495 return 0;
496 }
497 /*}}}*/
498 // PkgIterator::CurVersion - Returns the current version string /*{{{*/
499 // ---------------------------------------------------------------------
500 /* Return string representing of the current version. */
501 const char *
502 pkgCache::PkgIterator::CurVersion() const
503 {
504 VerIterator version = CurrentVer();
505 if (version.IsGood())
506 return CurrentVer().VerStr();
507 return 0;
508 }
509 /*}}}*/
510 // ostream operator to handle string representation of a package /*{{{*/
511 // ---------------------------------------------------------------------
512 /* Output name < cur.rent.version -> candid.ate.version | new.est.version > (section)
513 Note that the characters <|>() are all literal above. Versions will be omitted
514 if they provide no new information (e.g. there is no newer version than candidate)
515 If no version and/or section can be found "none" is used. */
516 std::ostream&
517 operator<<(std::ostream& out, pkgCache::PkgIterator Pkg)
518 {
519 if (Pkg.end() == true)
520 return out << "invalid package";
521
522 string current = string(Pkg.CurVersion() == 0 ? "none" : Pkg.CurVersion());
523 string candidate = string(Pkg.CandVersion() == 0 ? "none" : Pkg.CandVersion());
524 string newest = string(Pkg.VersionList().end() ? "none" : Pkg.VersionList().VerStr());
525
526 out << Pkg.Name() << " [ " << Pkg.Arch() << " ] < " << current;
527 if (current != candidate)
528 out << " -> " << candidate;
529 if ( newest != "none" && candidate != newest)
530 out << " | " << newest;
531 out << " > ( " << string(Pkg.Section()==0?"none":Pkg.Section()) << " )";
532 return out;
533 }
534 /*}}}*/
535 // PkgIterator::FullName - Returns Name and (maybe) Architecture /*{{{*/
536 // ---------------------------------------------------------------------
537 /* Returns a name:arch string */
538 std::string pkgCache::PkgIterator::FullName(bool const &Pretty) const
539 {
540 string fullname = Name();
541 if (Pretty == false ||
542 (strcmp(Arch(), "all") != 0 &&
543 strcmp(Owner->NativeArch(), Arch()) != 0))
544 return fullname.append(":").append(Arch());
545 return fullname;
546 }
547 /*}}}*/
548 // DepIterator::IsCritical - Returns true if the dep is important /*{{{*/
549 // ---------------------------------------------------------------------
550 /* Currently critical deps are defined as depends, predepends and
551 conflicts (including dpkg's Breaks fields). */
552 bool pkgCache::DepIterator::IsCritical() const
553 {
554 if (IsNegative() == true ||
555 S->Type == pkgCache::Dep::Depends ||
556 S->Type == pkgCache::Dep::PreDepends)
557 return true;
558 return false;
559 }
560 /*}}}*/
561 // DepIterator::IsNegative - Returns true if the dep is a negative one /*{{{*/
562 // ---------------------------------------------------------------------
563 /* Some dependencies are positive like Depends and Recommends, others
564 are negative like Conflicts which can and should be handled differently */
565 bool pkgCache::DepIterator::IsNegative() const
566 {
567 return S->Type == Dep::DpkgBreaks ||
568 S->Type == Dep::Conflicts ||
569 S->Type == Dep::Obsoletes;
570 }
571 /*}}}*/
572 // DepIterator::SmartTargetPkg - Resolve dep target pointers w/provides /*{{{*/
573 // ---------------------------------------------------------------------
574 /* This intellegently looks at dep target packages and tries to figure
575 out which package should be used. This is needed to nicely handle
576 provide mapping. If the target package has no other providing packages
577 then it returned. Otherwise the providing list is looked at to
578 see if there is one one unique providing package if so it is returned.
579 Otherwise true is returned and the target package is set. The return
580 result indicates whether the node should be expandable
581
582 In Conjunction with the DepCache the value of Result may not be
583 super-good since the policy may have made it uninstallable. Using
584 AllTargets is better in this case. */
585 bool pkgCache::DepIterator::SmartTargetPkg(PkgIterator &Result) const
586 {
587 Result = TargetPkg();
588
589 // No provides at all
590 if (Result->ProvidesList == 0)
591 return false;
592
593 // There is the Base package and the providing ones which is at least 2
594 if (Result->VersionList != 0)
595 return true;
596
597 /* We have to skip over indirect provisions of the package that
598 owns the dependency. For instance, if libc5-dev depends on the
599 virtual package libc-dev which is provided by libc5-dev and libc6-dev
600 we must ignore libc5-dev when considering the provides list. */
601 PrvIterator PStart = Result.ProvidesList();
602 for (; PStart.end() != true && PStart.OwnerPkg() == ParentPkg(); ++PStart);
603
604 // Nothing but indirect self provides
605 if (PStart.end() == true)
606 return false;
607
608 // Check for single packages in the provides list
609 PrvIterator P = PStart;
610 for (; P.end() != true; ++P)
611 {
612 // Skip over self provides
613 if (P.OwnerPkg() == ParentPkg())
614 continue;
615 if (PStart.OwnerPkg() != P.OwnerPkg())
616 break;
617 }
618
619 Result = PStart.OwnerPkg();
620
621 // Check for non dups
622 if (P.end() != true)
623 return true;
624
625 return false;
626 }
627 /*}}}*/
628 // DepIterator::AllTargets - Returns the set of all possible targets /*{{{*/
629 // ---------------------------------------------------------------------
630 /* This is a more useful version of TargetPkg() that follows versioned
631 provides. It includes every possible package-version that could satisfy
632 the dependency. The last item in the list has a 0. The resulting pointer
633 must be delete [] 'd */
634 pkgCache::Version **pkgCache::DepIterator::AllTargets() const
635 {
636 Version **Res = 0;
637 unsigned long Size =0;
638 while (1)
639 {
640 Version **End = Res;
641 PkgIterator DPkg = TargetPkg();
642
643 // Walk along the actual package providing versions
644 for (VerIterator I = DPkg.VersionList(); I.end() == false; ++I)
645 {
646 if (IsIgnorable(I.ParentPkg()) == true)
647 continue;
648 if (IsSatisfied(I) == false)
649 continue;
650
651 Size++;
652 if (Res != 0)
653 *End++ = I;
654 }
655
656 // Follow all provides
657 for (PrvIterator I = DPkg.ProvidesList(); I.end() == false; ++I)
658 {
659 if (IsIgnorable(I) == true)
660 continue;
661 if (IsSatisfied(I) == false)
662 continue;
663
664 Size++;
665 if (Res != 0)
666 *End++ = I.OwnerVer();
667 }
668
669 // Do it again and write it into the array
670 if (Res == 0)
671 {
672 Res = new Version *[Size+1];
673 Size = 0;
674 }
675 else
676 {
677 *End = 0;
678 break;
679 }
680 }
681
682 return Res;
683 }
684 /*}}}*/
685 // DepIterator::GlobOr - Compute an OR group /*{{{*/
686 // ---------------------------------------------------------------------
687 /* This Takes an iterator, iterates past the current dependency grouping
688 and returns Start and End so that so End is the final element
689 in the group, if End == Start then D is End++ and End is the
690 dependency D was pointing to. Use in loops to iterate sensibly. */
691 void pkgCache::DepIterator::GlobOr(DepIterator &Start,DepIterator &End)
692 {
693 // Compute a single dependency element (glob or)
694 Start = *this;
695 End = *this;
696 for (bool LastOR = true; end() == false && LastOR == true;)
697 {
698 LastOR = (S->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or;
699 (*this)++;
700 if (LastOR == true)
701 End = (*this);
702 }
703 }
704 /*}}}*/
705 // DepIterator::IsIgnorable - should this packag/providr be ignored? /*{{{*/
706 // ---------------------------------------------------------------------
707 /* Deps like self-conflicts should be ignored as well as implicit conflicts
708 on virtual packages. */
709 bool pkgCache::DepIterator::IsIgnorable(PkgIterator const &/*Pkg*/) const
710 {
711 if (IsNegative() == false)
712 return false;
713
714 pkgCache::PkgIterator PP = ParentPkg();
715 pkgCache::PkgIterator PT = TargetPkg();
716 if (PP->Group != PT->Group)
717 return false;
718 // self-conflict
719 if (PP == PT)
720 return true;
721 pkgCache::VerIterator PV = ParentVer();
722 // ignore group-conflict on a M-A:same package - but not our implicit dependencies
723 // so that we can have M-A:same packages conflicting with their own real name
724 if ((PV->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same)
725 {
726 // Replaces: ${self}:other ( << ${binary:Version})
727 if (S->Type == pkgCache::Dep::Replaces && S->CompareOp == pkgCache::Dep::Less && strcmp(PV.VerStr(), TargetVer()) == 0)
728 return false;
729 // Breaks: ${self}:other (!= ${binary:Version})
730 if (S->Type == pkgCache::Dep::DpkgBreaks && S->CompareOp == pkgCache::Dep::NotEquals && strcmp(PV.VerStr(), TargetVer()) == 0)
731 return false;
732 return true;
733 }
734
735 return false;
736 }
737 bool pkgCache::DepIterator::IsIgnorable(PrvIterator const &Prv) const
738 {
739 if (IsNegative() == false)
740 return false;
741
742 PkgIterator const Pkg = ParentPkg();
743 /* Provides may never be applied against the same package (or group)
744 if it is a conflicts. See the comment above. */
745 if (Prv.OwnerPkg()->Group == Pkg->Group)
746 return true;
747 // Implicit group-conflicts should not be applied on providers of other groups
748 if (Pkg->Group == TargetPkg()->Group && Prv.OwnerPkg()->Group != Pkg->Group)
749 return true;
750
751 return false;
752 }
753 /*}}}*/
754 // DepIterator::IsMultiArchImplicit - added by the cache generation /*{{{*/
755 // ---------------------------------------------------------------------
756 /* MultiArch can be translated to SingleArch for an resolver and we did so,
757 by adding dependencies to help the resolver understand the problem, but
758 sometimes it is needed to identify these to ignore them… */
759 bool pkgCache::DepIterator::IsMultiArchImplicit() const
760 {
761 if (ParentPkg()->Arch != TargetPkg()->Arch &&
762 (S->Type == pkgCache::Dep::Replaces ||
763 S->Type == pkgCache::Dep::DpkgBreaks ||
764 S->Type == pkgCache::Dep::Conflicts))
765 return true;
766 return false;
767 }
768 /*}}}*/
769 // DepIterator::IsSatisfied - check if a version satisfied the dependency /*{{{*/
770 bool pkgCache::DepIterator::IsSatisfied(VerIterator const &Ver) const
771 {
772 return Owner->VS->CheckDep(Ver.VerStr(),S->CompareOp,TargetVer());
773 }
774 bool pkgCache::DepIterator::IsSatisfied(PrvIterator const &Prv) const
775 {
776 return Owner->VS->CheckDep(Prv.ProvideVersion(),S->CompareOp,TargetVer());
777 }
778 /*}}}*/
779 // ostream operator to handle string representation of a dependecy /*{{{*/
780 // ---------------------------------------------------------------------
781 /* */
782 std::ostream& operator<<(std::ostream& out, pkgCache::DepIterator D)
783 {
784 if (D.end() == true)
785 return out << "invalid dependency";
786
787 pkgCache::PkgIterator P = D.ParentPkg();
788 pkgCache::PkgIterator T = D.TargetPkg();
789
790 out << (P.end() ? "invalid pkg" : P.FullName(false)) << " " << D.DepType()
791 << " on ";
792 if (T.end() == true)
793 out << "invalid pkg";
794 else
795 out << T;
796
797 if (D->Version != 0)
798 out << " (" << D.CompType() << " " << D.TargetVer() << ")";
799
800 return out;
801 }
802 /*}}}*/
803 // VerIterator::CompareVer - Fast version compare for same pkgs /*{{{*/
804 // ---------------------------------------------------------------------
805 /* This just looks over the version list to see if B is listed before A. In
806 most cases this will return in under 4 checks, ver lists are short. */
807 int pkgCache::VerIterator::CompareVer(const VerIterator &B) const
808 {
809 // Check if they are equal
810 if (*this == B)
811 return 0;
812 if (end() == true)
813 return -1;
814 if (B.end() == true)
815 return 1;
816
817 /* Start at A and look for B. If B is found then A > B otherwise
818 B was before A so A < B */
819 VerIterator I = *this;
820 for (;I.end() == false; ++I)
821 if (I == B)
822 return 1;
823 return -1;
824 }
825 /*}}}*/
826 // VerIterator::Downloadable - Checks if the version is downloadable /*{{{*/
827 // ---------------------------------------------------------------------
828 /* */
829 APT_PURE bool pkgCache::VerIterator::Downloadable() const
830 {
831 VerFileIterator Files = FileList();
832 for (; Files.end() == false; ++Files)
833 if ((Files.File()->Flags & pkgCache::Flag::NotSource) != pkgCache::Flag::NotSource)
834 return true;
835 return false;
836 }
837 /*}}}*/
838 // VerIterator::Automatic - Check if this version is 'automatic' /*{{{*/
839 // ---------------------------------------------------------------------
840 /* This checks to see if any of the versions files are not NotAutomatic.
841 True if this version is selectable for automatic installation. */
842 APT_PURE bool pkgCache::VerIterator::Automatic() const
843 {
844 VerFileIterator Files = FileList();
845 for (; Files.end() == false; ++Files)
846 // Do not check ButAutomaticUpgrades here as it is kind of automatic…
847 if ((Files.File()->Flags & pkgCache::Flag::NotAutomatic) != pkgCache::Flag::NotAutomatic)
848 return true;
849 return false;
850 }
851 /*}}}*/
852 // VerIterator::NewestFile - Return the newest file version relation /*{{{*/
853 // ---------------------------------------------------------------------
854 /* This looks at the version numbers associated with all of the sources
855 this version is in and returns the highest.*/
856 pkgCache::VerFileIterator pkgCache::VerIterator::NewestFile() const
857 {
858 VerFileIterator Files = FileList();
859 VerFileIterator Highest = Files;
860 for (; Files.end() == false; ++Files)
861 {
862 if (Owner->VS->CmpReleaseVer(Files.File().Version(),Highest.File().Version()) > 0)
863 Highest = Files;
864 }
865
866 return Highest;
867 }
868 /*}}}*/
869 // VerIterator::RelStr - Release description string /*{{{*/
870 // ---------------------------------------------------------------------
871 /* This describes the version from a release-centric manner. The output is a
872 list of Label:Version/Archive */
873 string pkgCache::VerIterator::RelStr() const
874 {
875 bool First = true;
876 string Res;
877 for (pkgCache::VerFileIterator I = this->FileList(); I.end() == false; ++I)
878 {
879 // Do not print 'not source' entries'
880 pkgCache::PkgFileIterator File = I.File();
881 if ((File->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource)
882 continue;
883
884 // See if we have already printed this out..
885 bool Seen = false;
886 for (pkgCache::VerFileIterator J = this->FileList(); I != J; ++J)
887 {
888 pkgCache::PkgFileIterator File2 = J.File();
889 if (File2->Label == 0 || File->Label == 0)
890 continue;
891
892 if (strcmp(File.Label(),File2.Label()) != 0)
893 continue;
894
895 if (File2->Version == File->Version)
896 {
897 Seen = true;
898 break;
899 }
900 if (File2->Version == 0 || File->Version == 0)
901 break;
902 if (strcmp(File.Version(),File2.Version()) == 0)
903 Seen = true;
904 }
905
906 if (Seen == true)
907 continue;
908
909 if (First == false)
910 Res += ", ";
911 else
912 First = false;
913
914 if (File->Label != 0)
915 Res = Res + File.Label() + ':';
916
917 if (File->Archive != 0)
918 {
919 if (File->Version == 0)
920 Res += File.Archive();
921 else
922 Res = Res + File.Version() + '/' + File.Archive();
923 }
924 else
925 {
926 // No release file, print the host name that this came from
927 if (File->Site == 0 || File.Site()[0] == 0)
928 Res += "localhost";
929 else
930 Res += File.Site();
931 }
932 }
933 if (S->ParentPkg != 0)
934 Res.append(" [").append(Arch()).append("]");
935 return Res;
936 }
937 /*}}}*/
938 // VerIterator::MultiArchType - string representing MultiArch flag /*{{{*/
939 const char * pkgCache::VerIterator::MultiArchType() const
940 {
941 if ((S->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same)
942 return "same";
943 else if ((S->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign)
944 return "foreign";
945 else if ((S->MultiArch & pkgCache::Version::Allowed) == pkgCache::Version::Allowed)
946 return "allowed";
947 return "none";
948 }
949 /*}}}*/
950 // PkgFileIterator::IsOk - Checks if the cache is in sync with the file /*{{{*/
951 // ---------------------------------------------------------------------
952 /* This stats the file and compares its stats with the ones that were
953 stored during generation. Date checks should probably also be
954 included here. */
955 bool pkgCache::PkgFileIterator::IsOk()
956 {
957 struct stat Buf;
958 if (stat(FileName(),&Buf) != 0)
959 return false;
960
961 if (Buf.st_size != (signed)S->Size || Buf.st_mtime != S->mtime)
962 return false;
963
964 return true;
965 }
966 /*}}}*/
967 // PkgFileIterator::RelStr - Return the release string /*{{{*/
968 // ---------------------------------------------------------------------
969 /* */
970 string pkgCache::PkgFileIterator::RelStr()
971 {
972 string Res;
973 if (Version() != 0)
974 Res = Res + (Res.empty() == true?"v=":",v=") + Version();
975 if (Origin() != 0)
976 Res = Res + (Res.empty() == true?"o=":",o=") + Origin();
977 if (Archive() != 0)
978 Res = Res + (Res.empty() == true?"a=":",a=") + Archive();
979 if (Codename() != 0)
980 Res = Res + (Res.empty() == true?"n=":",n=") + Codename();
981 if (Label() != 0)
982 Res = Res + (Res.empty() == true?"l=":",l=") + Label();
983 if (Component() != 0)
984 Res = Res + (Res.empty() == true?"c=":",c=") + Component();
985 if (Architecture() != 0)
986 Res = Res + (Res.empty() == true?"b=":",b=") + Architecture();
987 return Res;
988 }
989 /*}}}*/
990 // VerIterator::TranslatedDescription - Return the a DescIter for locale/*{{{*/
991 // ---------------------------------------------------------------------
992 /* return a DescIter for the current locale or the default if none is
993 * found
994 */
995 pkgCache::DescIterator pkgCache::VerIterator::TranslatedDescription() const
996 {
997 std::vector<string> const lang = APT::Configuration::getLanguages();
998 for (std::vector<string>::const_iterator l = lang.begin();
999 l != lang.end(); ++l)
1000 {
1001 pkgCache::DescIterator Desc = DescriptionList();
1002 for (; Desc.end() == false; ++Desc)
1003 if (*l == Desc.LanguageCode())
1004 break;
1005 if (Desc.end() == true)
1006 {
1007 if (*l == "en")
1008 {
1009 Desc = DescriptionList();
1010 for (; Desc.end() == false; ++Desc)
1011 if (strcmp(Desc.LanguageCode(), "") == 0)
1012 break;
1013 if (Desc.end() == true)
1014 continue;
1015 }
1016 else
1017 continue;
1018 }
1019 return Desc;
1020 }
1021 for (pkgCache::DescIterator Desc = DescriptionList();
1022 Desc.end() == false; ++Desc)
1023 if (strcmp(Desc.LanguageCode(), "") == 0)
1024 return Desc;
1025 return DescriptionList();
1026 }
1027
1028 /*}}}*/
1029 // PrvIterator::IsMultiArchImplicit - added by the cache generation /*{{{*/
1030 // ---------------------------------------------------------------------
1031 /* MultiArch can be translated to SingleArch for an resolver and we did so,
1032 by adding provides to help the resolver understand the problem, but
1033 sometimes it is needed to identify these to ignore them… */
1034 bool pkgCache::PrvIterator::IsMultiArchImplicit() const
1035 {
1036 pkgCache::PkgIterator const Owner = OwnerPkg();
1037 pkgCache::PkgIterator const Parent = ParentPkg();
1038 if (strcmp(Owner.Arch(), Parent.Arch()) != 0 || Owner->Name == Parent->Name)
1039 return true;
1040 return false;
1041 }
1042 /*}}}*/