]> git.saurik.com Git - apt.git/blob - apt-pkg/pkgcache.cc
Add support for calculating hashes over the entire cache
[apt.git] / apt-pkg / pkgcache.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: pkgcache.cc,v 1.37 2003/02/10 01:40:58 doogie Exp $
4 /* ######################################################################
5
6 Package Cache - Accessor code for the cache
7
8 Please see doc/apt-pkg/cache.sgml for a more detailed description of
9 this format. Also be sure to keep that file up-to-date!!
10
11 This is the general utility functions for cache management. They provide
12 a complete set of accessor functions for the cache. The cacheiterators
13 header contains the STL-like iterators that can be used to easially
14 navigate the cache as well as seemlessly dereference the mmap'd
15 indexes. Use these always.
16
17 The main class provides for ways to get package indexes and some
18 general lookup functions to start the iterators.
19
20 ##################################################################### */
21 /*}}}*/
22 // Include Files /*{{{*/
23 #include<config.h>
24
25 #include <apt-pkg/pkgcache.h>
26 #include <apt-pkg/policy.h>
27 #include <apt-pkg/version.h>
28 #include <apt-pkg/error.h>
29 #include <apt-pkg/strutl.h>
30 #include <apt-pkg/configuration.h>
31 #include <apt-pkg/aptconfiguration.h>
32 #include <apt-pkg/mmap.h>
33 #include <apt-pkg/macros.h>
34
35 #include <stddef.h>
36 #include <string.h>
37 #include <sstream>
38 #include <algorithm>
39 #include <vector>
40 #include <string>
41 #include <sys/stat.h>
42 #include <zlib.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, 3);
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", 15013));
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 (HeaderP->VerSysName == 0 || HeaderP->Architecture == 0 || HeaderP->GetArchitectures() == 0)
178 return _error->Error(_("The package cache file is corrupted"));
179
180 // Locate our VS..
181 if ((VS = pkgVersioningSystem::GetVS(StrP + HeaderP->VerSysName)) == 0)
182 return _error->Error(_("This APT does not support the versioning system '%s'"),StrP + HeaderP->VerSysName);
183
184 // Check the architecture
185 std::vector<std::string> archs = APT::Configuration::getArchitectures();
186 std::vector<std::string>::const_iterator a = archs.begin();
187 std::string list = *a;
188 for (++a; a != archs.end(); ++a)
189 list.append(",").append(*a);
190 if (_config->Find("APT::Architecture") != StrP + HeaderP->Architecture ||
191 list != StrP + HeaderP->GetArchitectures())
192 return _error->Error(_("The package cache was built for different architectures: %s vs %s"), StrP + HeaderP->GetArchitectures(), list.c_str());
193
194
195 auto hash = CacheHash();
196 if (_config->FindB("Debug::pkgCacheGen", false))
197 std::clog << "Opened cache with hash " << hash << ", expecting " << HeaderP->CacheFileSize << "\n";
198 if (hash != HeaderP->CacheFileSize)
199 return _error->Error(_("The package cache file is corrupted, it has the wrong hash"));
200
201 return true;
202 }
203 /*}}}*/
204 // Cache::Hash - Hash a string /*{{{*/
205 // ---------------------------------------------------------------------
206 /* This is used to generate the hash entries for the HashTable. With my
207 package list from bo this function gets 94% table usage on a 512 item
208 table (480 used items) */
209 map_id_t pkgCache::sHash(const string &Str) const
210 {
211 uint32_t Hash = 5381;
212 for (string::const_iterator I = Str.begin(); I != Str.end(); ++I)
213 Hash = 33 * Hash + tolower_ascii(*I);
214 return Hash % HeaderP->GetHashTableSize();
215 }
216
217 map_id_t pkgCache::sHash(const char *Str) const
218 {
219 uint32_t Hash = 5381;
220 for (const char *I = Str; *I != 0; ++I)
221 Hash = 33 * Hash + tolower_ascii(*I);
222 return Hash % HeaderP->GetHashTableSize();
223 }
224
225 uint32_t pkgCache::CacheHash()
226 {
227 pkgCache::Header header = {};
228 uLong adler = adler32(0L, Z_NULL, 0);
229
230 if (Map.Size() < sizeof(header))
231 return adler;
232 memcpy(&header, GetMap().Data(), sizeof(header));
233
234 header.Dirty = false;
235 header.CacheFileSize = 0;
236
237 adler = adler32(adler,
238 reinterpret_cast<const unsigned char *>(&header),
239 sizeof(header));
240
241 if (Map.Size() > sizeof(header)) {
242 adler = adler32(adler,
243 static_cast<const unsigned char *>(GetMap().Data()) + sizeof(header),
244 GetMap().Size() - sizeof(header));
245 }
246
247 return adler;
248 }
249 /*}}}*/
250 // Cache::FindPkg - Locate a package by name /*{{{*/
251 // ---------------------------------------------------------------------
252 /* Returns 0 on error, pointer to the package otherwise */
253 pkgCache::PkgIterator pkgCache::FindPkg(const string &Name) {
254 size_t const found = Name.find(':');
255 if (found == string::npos)
256 return FindPkg(Name, "native");
257 string const Arch = Name.substr(found+1);
258 /* Beware: This is specialcased to handle pkg:any in dependencies
259 as these are linked to virtual pkg:any named packages.
260 If you want any arch from a pkg, use FindPkg(pkg,"any") */
261 if (Arch == "any")
262 return FindPkg(Name, "any");
263 return FindPkg(Name.substr(0, found), Arch);
264 }
265 /*}}}*/
266 // Cache::FindPkg - Locate a package by name /*{{{*/
267 // ---------------------------------------------------------------------
268 /* Returns 0 on error, pointer to the package otherwise */
269 pkgCache::PkgIterator pkgCache::FindPkg(const string &Name, string const &Arch) {
270 /* We make a detour via the GrpIterator here as
271 on a multi-arch environment a group is easier to
272 find than a package (less entries in the buckets) */
273 pkgCache::GrpIterator Grp = FindGrp(Name);
274 if (Grp.end() == true)
275 return PkgIterator(*this,0);
276
277 return Grp.FindPkg(Arch);
278 }
279 /*}}}*/
280 // Cache::FindGrp - Locate a group by name /*{{{*/
281 // ---------------------------------------------------------------------
282 /* Returns End-Pointer on error, pointer to the group otherwise */
283 pkgCache::GrpIterator pkgCache::FindGrp(const string &Name) {
284 if (unlikely(Name.empty() == true))
285 return GrpIterator(*this,0);
286
287 // Look at the hash bucket for the group
288 Group *Grp = GrpP + HeaderP->GrpHashTableP()[sHash(Name)];
289 for (; Grp != GrpP; Grp = GrpP + Grp->Next) {
290 int const cmp = strcmp(Name.c_str(), StrP + Grp->Name);
291 if (cmp == 0)
292 return GrpIterator(*this, Grp);
293 else if (cmp < 0)
294 break;
295 }
296
297 return GrpIterator(*this,0);
298 }
299 /*}}}*/
300 // Cache::CompTypeDeb - Return a string describing the compare type /*{{{*/
301 // ---------------------------------------------------------------------
302 /* This returns a string representation of the dependency compare
303 type in the weird debian style.. */
304 const char *pkgCache::CompTypeDeb(unsigned char Comp)
305 {
306 const char * const Ops[] = {"","<=",">=","<<",">>","=","!="};
307 if (unlikely((unsigned)(Comp & 0xF) >= sizeof(Ops)/sizeof(Ops[0])))
308 return "";
309 return Ops[Comp & 0xF];
310 }
311 /*}}}*/
312 // Cache::CompType - Return a string describing the compare type /*{{{*/
313 // ---------------------------------------------------------------------
314 /* This returns a string representation of the dependency compare
315 type */
316 const char *pkgCache::CompType(unsigned char Comp)
317 {
318 const char * const Ops[] = {"","<=",">=","<",">","=","!="};
319 if (unlikely((unsigned)(Comp & 0xF) >= sizeof(Ops)/sizeof(Ops[0])))
320 return "";
321 return Ops[Comp & 0xF];
322 }
323 /*}}}*/
324 // Cache::DepType - Return a string describing the dep type /*{{{*/
325 // ---------------------------------------------------------------------
326 /* */
327 const char *pkgCache::DepType(unsigned char Type)
328 {
329 const char *Types[] = {"",_("Depends"),_("PreDepends"),_("Suggests"),
330 _("Recommends"),_("Conflicts"),_("Replaces"),
331 _("Obsoletes"),_("Breaks"), _("Enhances")};
332 if (Type < sizeof(Types)/sizeof(*Types))
333 return Types[Type];
334 return "";
335 }
336 /*}}}*/
337 // Cache::Priority - Convert a priority value to a string /*{{{*/
338 // ---------------------------------------------------------------------
339 /* */
340 const char *pkgCache::Priority(unsigned char Prio)
341 {
342 const char *Mapping[] = {0,_("required"),_("important"),_("standard"),
343 _("optional"),_("extra")};
344 if (Prio < _count(Mapping))
345 return Mapping[Prio];
346 return 0;
347 }
348 /*}}}*/
349 // GrpIterator::FindPkg - Locate a package by arch /*{{{*/
350 // ---------------------------------------------------------------------
351 /* Returns an End-Pointer on error, pointer to the package otherwise */
352 pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) const {
353 if (unlikely(IsGood() == false || S->FirstPackage == 0))
354 return PkgIterator(*Owner, 0);
355
356 /* If we accept any package we simply return the "first"
357 package in this group */
358 if (Arch == "any")
359 return PkgIterator(*Owner, Owner->PkgP + S->FirstPackage);
360 if (Arch == "native" || Arch == "all")
361 Arch = Owner->NativeArch();
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 && strcmp(Arch(), "any") != 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() {}