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