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