]> git.saurik.com Git - apt.git/blame - apt-pkg/pkgcache.cc
Add support for calculating hashes over the entire cache
[apt.git] / apt-pkg / pkgcache.cc
CommitLineData
578bfd0a
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
bac2e715 3// $Id: pkgcache.cc,v 1.37 2003/02/10 01:40:58 doogie Exp $
578bfd0a
AL
4/* ######################################################################
5
6 Package Cache - Accessor code for the cache
7
094a497d 8 Please see doc/apt-pkg/cache.sgml for a more detailed description of
578bfd0a
AL
9 this format. Also be sure to keep that file up-to-date!!
10
1e3f4083 11 This is the general utility functions for cache management. They provide
578bfd0a
AL
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 /*{{{*/
ea542140
DK
23#include<config.h>
24
094a497d 25#include <apt-pkg/pkgcache.h>
af29ffb4 26#include <apt-pkg/policy.h>
094a497d
AL
27#include <apt-pkg/version.h>
28#include <apt-pkg/error.h>
231fea14 29#include <apt-pkg/strutl.h>
b2e465d6 30#include <apt-pkg/configuration.h>
45df0ad2 31#include <apt-pkg/aptconfiguration.h>
453b82a3 32#include <apt-pkg/mmap.h>
5c0d3668 33#include <apt-pkg/macros.h>
578bfd0a 34
453b82a3
DK
35#include <stddef.h>
36#include <string.h>
7f8c0eed
DK
37#include <sstream>
38#include <algorithm>
453b82a3 39#include <vector>
578bfd0a
AL
40#include <string>
41#include <sys/stat.h>
25c7a09d 42#include <zlib.h>
ea542140
DK
43
44#include <apti18n.h>
578bfd0a
AL
45 /*}}}*/
46
851a45a8
AL
47using std::string;
48
012b102a 49
578bfd0a
AL
50// Cache::Header::Header - Constructor /*{{{*/
51// ---------------------------------------------------------------------
52/* Simply initialize the header */
53pkgCache::Header::Header()
54{
dfe66c72
DK
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
578bfd0a
AL
58 /* Whenever the structures change the major version should be bumped,
59 whenever the generator changes the minor version should be bumped. */
dfe66c72 60 APT_HEADER_SET(MajorVersion, 10);
0748f03a 61 APT_HEADER_SET(MinorVersion, 3);
dfe66c72
DK
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
52c41485 78 GroupCount = 0;
578bfd0a
AL
79 PackageCount = 0;
80 VersionCount = 0;
a52f938b 81 DescriptionCount = 0;
578bfd0a 82 DependsCount = 0;
71c9e95b 83 DependsDataCount = 0;
b07aeb1a 84 ReleaseFileCount = 0;
578bfd0a 85 PackageFileCount = 0;
a7e66b17 86 VerFileCount = 0;
a52f938b 87 DescFileCount = 0;
a7e66b17 88 ProvidesCount = 0;
ad00ae81 89 MaxVerFileSize = 0;
a52f938b 90 MaxDescFileSize = 0;
dfe66c72 91
578bfd0a 92 FileList = 0;
b07aeb1a 93 RlsFileList = 0;
b2e465d6
AL
94 VerSysName = 0;
95 Architecture = 0;
32ab4bd0 96 SetArchitectures(0);
0748f03a 97 SetHashTableSize(_config->FindI("APT::Cache-HashTableSize", 15013));
578bfd0a 98 memset(Pools,0,sizeof(Pools));
0688ccd8
JAK
99
100 CacheFileSize = 0;
578bfd0a
AL
101}
102 /*}}}*/
103// Cache::Header::CheckSizes - Check if the two headers have same *sz /*{{{*/
104// ---------------------------------------------------------------------
105/* */
106bool pkgCache::Header::CheckSizes(Header &Against) const
107{
108 if (HeaderSz == Against.HeaderSz &&
52c41485 109 GroupSz == Against.GroupSz &&
578bfd0a 110 PackageSz == Against.PackageSz &&
b07aeb1a 111 ReleaseFileSz == Against.ReleaseFileSz &&
578bfd0a
AL
112 PackageFileSz == Against.PackageFileSz &&
113 VersionSz == Against.VersionSz &&
a52f938b 114 DescriptionSz == Against.DescriptionSz &&
dcb79bae 115 DependencySz == Against.DependencySz &&
71c9e95b 116 DependencyDataSz == Against.DependencyDataSz &&
dcb79bae 117 VerFileSz == Against.VerFileSz &&
a52f938b 118 DescFileSz == Against.DescFileSz &&
578bfd0a
AL
119 ProvidesSz == Against.ProvidesSz)
120 return true;
121 return false;
122}
123 /*}}}*/
124
125// Cache::pkgCache - Constructor /*{{{*/
126// ---------------------------------------------------------------------
127/* */
32ab4bd0 128APT_IGNORE_DEPRECATED_PUSH
6c55f07a 129pkgCache::pkgCache(MMap *Map, bool DoMap) : Map(*Map), d(NULL)
578bfd0a 130{
4cbf323f
MV
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;
b2e465d6
AL
135 if (DoMap == true)
136 ReMap();
578bfd0a 137}
32ab4bd0 138APT_IGNORE_DEPRECATED_POP
578bfd0a
AL
139 /*}}}*/
140// Cache::ReMap - Reopen the cache file /*{{{*/
141// ---------------------------------------------------------------------
142/* If the file is already closed then this will open it open it. */
a9fe5928 143bool pkgCache::ReMap(bool const &Errorchecks)
578bfd0a
AL
144{
145 // Apply the typecasts.
146 HeaderP = (Header *)Map.Data();
5bf15716 147 GrpP = (Group *)Map.Data();
578bfd0a 148 PkgP = (Package *)Map.Data();
dcb79bae 149 VerFileP = (VerFile *)Map.Data();
a52f938b 150 DescFileP = (DescFile *)Map.Data();
b07aeb1a 151 RlsFileP = (ReleaseFile *)Map.Data();
578bfd0a
AL
152 PkgFileP = (PackageFile *)Map.Data();
153 VerP = (Version *)Map.Data();
a52f938b 154 DescP = (Description *)Map.Data();
578bfd0a
AL
155 ProvideP = (Provides *)Map.Data();
156 DepP = (Dependency *)Map.Data();
71c9e95b 157 DepDataP = (DependencyData *)Map.Data();
578bfd0a
AL
158 StrP = (char *)Map.Data();
159
a9fe5928
DK
160 if (Errorchecks == false)
161 return true;
162
b2e465d6
AL
163 if (Map.Size() == 0 || HeaderP == 0)
164 return _error->Error(_("Empty package cache"));
578bfd0a
AL
165
166 // Check the header
167 Header DefHeader;
168 if (HeaderP->Signature != DefHeader.Signature ||
169 HeaderP->Dirty == true)
b2e465d6 170 return _error->Error(_("The package cache file is corrupted"));
578bfd0a
AL
171
172 if (HeaderP->MajorVersion != DefHeader.MajorVersion ||
173 HeaderP->MinorVersion != DefHeader.MinorVersion ||
174 HeaderP->CheckSizes(DefHeader) == false)
b2e465d6
AL
175 return _error->Error(_("The package cache file is an incompatible version"));
176
32ab4bd0 177 if (HeaderP->VerSysName == 0 || HeaderP->Architecture == 0 || HeaderP->GetArchitectures() == 0)
7a223b93
DK
178 return _error->Error(_("The package cache file is corrupted"));
179
b2e465d6 180 // Locate our VS..
7a223b93 181 if ((VS = pkgVersioningSystem::GetVS(StrP + HeaderP->VerSysName)) == 0)
db0db9fe 182 return _error->Error(_("This APT does not support the versioning system '%s'"),StrP + HeaderP->VerSysName);
b2e465d6 183
7a223b93
DK
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 ||
32ab4bd0
DK
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());
7a223b93 193
25c7a09d
JAK
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
578bfd0a
AL
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) */
4ad8619b 209map_id_t pkgCache::sHash(const string &Str) const
578bfd0a 210{
0748f03a 211 uint32_t Hash = 5381;
f7f0d6c7 212 for (string::const_iterator I = Str.begin(); I != Str.end(); ++I)
0748f03a 213 Hash = 33 * Hash + tolower_ascii(*I);
32ab4bd0 214 return Hash % HeaderP->GetHashTableSize();
578bfd0a
AL
215}
216
4ad8619b 217map_id_t pkgCache::sHash(const char *Str) const
578bfd0a 218{
0748f03a
JAK
219 uint32_t Hash = 5381;
220 for (const char *I = Str; *I != 0; ++I)
221 Hash = 33 * Hash + tolower_ascii(*I);
32ab4bd0 222 return Hash % HeaderP->GetHashTableSize();
578bfd0a 223}
25c7a09d
JAK
224
225uint32_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}
8d4c859d 249 /*}}}*/
578bfd0a
AL
250// Cache::FindPkg - Locate a package by name /*{{{*/
251// ---------------------------------------------------------------------
252/* Returns 0 on error, pointer to the package otherwise */
25396fb0
DK
253pkgCache::PkgIterator pkgCache::FindPkg(const string &Name) {
254 size_t const found = Name.find(':');
255 if (found == string::npos)
6c9937da 256 return FindPkg(Name, "native");
4d174dc8 257 string const Arch = Name.substr(found+1);
8fec289a
DK
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") */
4d174dc8
DK
261 if (Arch == "any")
262 return FindPkg(Name, "any");
263 return FindPkg(Name.substr(0, found), Arch);
25396fb0
DK
264}
265 /*}}}*/
266// Cache::FindPkg - Locate a package by name /*{{{*/
267// ---------------------------------------------------------------------
268/* Returns 0 on error, pointer to the package otherwise */
8d4c859d 269pkgCache::PkgIterator pkgCache::FindPkg(const string &Name, string const &Arch) {
5bf15716
DK
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 */
283pkgCache::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
32ab4bd0 288 Group *Grp = GrpP + HeaderP->GrpHashTableP()[sHash(Name)];
5bf15716 289 for (; Grp != GrpP; Grp = GrpP + Grp->Next) {
b59325e8 290 int const cmp = strcmp(Name.c_str(), StrP + Grp->Name);
aa0fe657 291 if (cmp == 0)
5bf15716 292 return GrpIterator(*this, Grp);
aa0fe657
DK
293 else if (cmp < 0)
294 break;
5bf15716
DK
295 }
296
297 return GrpIterator(*this,0);
578bfd0a
AL
298}
299 /*}}}*/
b2e465d6
AL
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.. */
304const char *pkgCache::CompTypeDeb(unsigned char Comp)
305{
69c2ecbd
DK
306 const char * const Ops[] = {"","<=",">=","<<",">>","=","!="};
307 if (unlikely((unsigned)(Comp & 0xF) >= sizeof(Ops)/sizeof(Ops[0])))
308 return "";
309 return Ops[Comp & 0xF];
b2e465d6
AL
310}
311 /*}}}*/
312// Cache::CompType - Return a string describing the compare type /*{{{*/
313// ---------------------------------------------------------------------
69c2ecbd 314/* This returns a string representation of the dependency compare
b2e465d6
AL
315 type */
316const char *pkgCache::CompType(unsigned char Comp)
317{
69c2ecbd
DK
318 const char * const Ops[] = {"","<=",">=","<",">","=","!="};
319 if (unlikely((unsigned)(Comp & 0xF) >= sizeof(Ops)/sizeof(Ops[0])))
320 return "";
321 return Ops[Comp & 0xF];
b2e465d6
AL
322}
323 /*}}}*/
324// Cache::DepType - Return a string describing the dep type /*{{{*/
325// ---------------------------------------------------------------------
326/* */
327const char *pkgCache::DepType(unsigned char Type)
328{
329 const char *Types[] = {"",_("Depends"),_("PreDepends"),_("Suggests"),
330 _("Recommends"),_("Conflicts"),_("Replaces"),
f8ae7e8b 331 _("Obsoletes"),_("Breaks"), _("Enhances")};
308c7d30 332 if (Type < sizeof(Types)/sizeof(*Types))
b2e465d6
AL
333 return Types[Type];
334 return "";
335}
336 /*}}}*/
0149949b
AL
337// Cache::Priority - Convert a priority value to a string /*{{{*/
338// ---------------------------------------------------------------------
339/* */
340const char *pkgCache::Priority(unsigned char Prio)
341{
2fcd25a9 342 const char *Mapping[] = {0,_("required"),_("important"),_("standard"),
b2e465d6 343 _("optional"),_("extra")};
0149949b
AL
344 if (Prio < _count(Mapping))
345 return Mapping[Prio];
346 return 0;
347}
348 /*}}}*/
5bf15716
DK
349// GrpIterator::FindPkg - Locate a package by arch /*{{{*/
350// ---------------------------------------------------------------------
351/* Returns an End-Pointer on error, pointer to the package otherwise */
e841200b 352pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) const {
5bf15716
DK
353 if (unlikely(IsGood() == false || S->FirstPackage == 0))
354 return PkgIterator(*Owner, 0);
355
60dcec6d 356 /* If we accept any package we simply return the "first"
8fec289a 357 package in this group */
60dcec6d
DK
358 if (Arch == "any")
359 return PkgIterator(*Owner, Owner->PkgP + S->FirstPackage);
8fec289a
DK
360 if (Arch == "native" || Arch == "all")
361 Arch = Owner->NativeArch();
5bf15716 362
5d1e330d 363 // Iterate over the list to find the matching arch
5bf15716 364 for (pkgCache::Package *Pkg = PackageList(); Pkg != Owner->PkgP;
32ab4bd0 365 Pkg = Owner->PkgP + Pkg->NextPackage) {
5d1e330d 366 if (stringcmp(Arch, Owner->StrP + Pkg->Arch) == 0)
5bf15716
DK
367 return PkgIterator(*Owner, Pkg);
368 if ((Owner->PkgP + S->LastPackage) == Pkg)
369 break;
370 }
371
bd2fb30a
DK
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 */
3db58cf4 378pkgCache::PkgIterator pkgCache::GrpIterator::FindPreferredPkg(bool const &PreferNonVirtual) const {
bd2fb30a 379 pkgCache::PkgIterator Pkg = FindPkg("native");
3db58cf4 380 if (Pkg.end() == false && (PreferNonVirtual == false || Pkg->VersionList != 0))
bd2fb30a
DK
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);
3db58cf4 387 if (Pkg.end() == false && (PreferNonVirtual == false || Pkg->VersionList != 0))
bd2fb30a
DK
388 return Pkg;
389 }
c919ad6e
DK
390 // packages without an architecture
391 Pkg = FindPkg("none");
392 if (Pkg.end() == false && (PreferNonVirtual == false || Pkg->VersionList != 0))
393 return Pkg;
bd2fb30a 394
3db58cf4
DK
395 if (PreferNonVirtual == true)
396 return FindPreferredPkg(false);
5bf15716
DK
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.
c408e01e
DK
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) */
e841200b 405pkgCache::PkgIterator pkgCache::GrpIterator::NextPkg(pkgCache::PkgIterator const &LastPkg) const {
5bf15716
DK
406 if (unlikely(IsGood() == false || S->FirstPackage == 0 ||
407 LastPkg.end() == true))
408 return PkgIterator(*Owner, 0);
409
c408e01e
DK
410 if (S->LastPackage == LastPkg.Index())
411 return PkgIterator(*Owner, 0);
5bf15716 412
32ab4bd0 413 return PkgIterator(*Owner, Owner->PkgP + LastPkg->NextPackage);
5bf15716
DK
414}
415 /*}}}*/
71c9e95b 416// GrpIterator::operator++ - Prefix incr /*{{{*/
25396fb0
DK
417// ---------------------------------------------------------------------
418/* This will advance to the next logical group in the hash table. */
3707fd4f 419pkgCache::GrpIterator& pkgCache::GrpIterator::operator++()
25396fb0
DK
420{
421 // Follow the current links
422 if (S != Owner->GrpP)
423 S = Owner->GrpP + S->Next;
424
425 // Follow the hash table
32ab4bd0 426 while (S == Owner->GrpP && (HashIndex+1) < (signed)Owner->HeaderP->GetHashTableSize())
25396fb0 427 {
71c9e95b 428 ++HashIndex;
32ab4bd0 429 S = Owner->GrpP + Owner->HeaderP->GrpHashTableP()[HashIndex];
25396fb0 430 }
3707fd4f 431 return *this;
d3e8fbb3 432}
f55a958f 433 /*}}}*/
71c9e95b 434// PkgIterator::operator++ - Prefix incr /*{{{*/
578bfd0a
AL
435// ---------------------------------------------------------------------
436/* This will advance to the next logical package in the hash table. */
71c9e95b 437pkgCache::PkgIterator& pkgCache::PkgIterator::operator++()
578bfd0a
AL
438{
439 // Follow the current links
773e2c1f 440 if (S != Owner->PkgP)
32ab4bd0 441 S = Owner->PkgP + S->NextPackage;
b2e465d6 442
578bfd0a 443 // Follow the hash table
32ab4bd0 444 while (S == Owner->PkgP && (HashIndex+1) < (signed)Owner->HeaderP->GetHashTableSize())
578bfd0a 445 {
71c9e95b 446 ++HashIndex;
32ab4bd0 447 S = Owner->PkgP + Owner->HeaderP->PkgHashTableP()[HashIndex];
578bfd0a 448 }
3707fd4f 449 return *this;
d3e8fbb3 450}
578bfd0a 451 /*}}}*/
71c9e95b
DK
452pkgCache::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 /*}}}*/
578bfd0a
AL
464// PkgIterator::State - Check the State of the package /*{{{*/
465// ---------------------------------------------------------------------
466/* By this we mean if it is either cleanly installed or cleanly removed. */
467pkgCache::PkgIterator::OkState pkgCache::PkgIterator::State() const
d38b7b3d 468{
773e2c1f
DK
469 if (S->InstState == pkgCache::State::ReInstReq ||
470 S->InstState == pkgCache::State::HoldReInstReq)
c7c1b0f6
AL
471 return NeedsUnpack;
472
773e2c1f
DK
473 if (S->CurrentState == pkgCache::State::UnPacked ||
474 S->CurrentState == pkgCache::State::HalfConfigured)
c6aa14e4
MV
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
09fab244 479 //Pkg->CurrentState == pkgCache::State::TriggersAwaited
c6aa14e4 480 //Pkg->CurrentState == pkgCache::State::TriggersPending)
578bfd0a
AL
481 return NeedsConfigure;
482
773e2c1f
DK
483 if (S->CurrentState == pkgCache::State::HalfInstalled ||
484 S->InstState != pkgCache::State::Ok)
578bfd0a
AL
485 return NeedsUnpack;
486
487 return NeedsNothing;
488}
489 /*}}}*/
af29ffb4
MV
490// PkgIterator::CandVersion - Returns the candidate version string /*{{{*/
491// ---------------------------------------------------------------------
492/* Return string representing of the candidate version. */
493const char *
d3e8fbb3 494pkgCache::PkgIterator::CandVersion() const
af29ffb4
MV
495{
496 //TargetVer is empty, so don't use it.
749eb4cf 497 VerIterator version = pkgPolicy(Owner).GetCandidateVer(*this);
af29ffb4
MV
498 if (version.IsGood())
499 return version.VerStr();
500 return 0;
d3e8fbb3 501}
af29ffb4
MV
502 /*}}}*/
503// PkgIterator::CurVersion - Returns the current version string /*{{{*/
504// ---------------------------------------------------------------------
505/* Return string representing of the current version. */
506const char *
d3e8fbb3 507pkgCache::PkgIterator::CurVersion() const
af29ffb4
MV
508{
509 VerIterator version = CurrentVer();
510 if (version.IsGood())
511 return CurrentVer().VerStr();
512 return 0;
d3e8fbb3 513}
af29ffb4
MV
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)
1e3f4083 518 Note that the characters <|>() are all literal above. Versions will be omitted
af29ffb4
MV
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. */
521std::ostream&
8f3ba4e8 522operator<<(std::ostream& out, pkgCache::PkgIterator Pkg)
af29ffb4
MV
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
5dd4c8b8 531 out << Pkg.Name() << " [ " << Pkg.Arch() << " ] < " << current;
af29ffb4
MV
532 if (current != candidate)
533 out << " -> " << candidate;
534 if ( newest != "none" && candidate != newest)
535 out << " | " << newest;
7a669774
DK
536 if (Pkg->VersionList == 0)
537 out << " > ( none )";
538 else
539 out << " > ( " << string(Pkg.VersionList().Section()==0?"unknown":Pkg.VersionList().Section()) << " )";
af29ffb4
MV
540 return out;
541}
542 /*}}}*/
75ce2062
DK
543// PkgIterator::FullName - Returns Name and (maybe) Architecture /*{{{*/
544// ---------------------------------------------------------------------
545/* Returns a name:arch string */
546std::string pkgCache::PkgIterator::FullName(bool const &Pretty) const
547{
548 string fullname = Name();
549 if (Pretty == false ||
f6ce7ffc 550 (strcmp(Arch(), "all") != 0 && strcmp(Arch(), "any") != 0 &&
959470da 551 strcmp(Owner->NativeArch(), Arch()) != 0))
75ce2062
DK
552 return fullname.append(":").append(Arch());
553 return fullname;
554}
555 /*}}}*/
578bfd0a
AL
556// DepIterator::IsCritical - Returns true if the dep is important /*{{{*/
557// ---------------------------------------------------------------------
558/* Currently critical deps are defined as depends, predepends and
308c7d30 559 conflicts (including dpkg's Breaks fields). */
e841200b 560bool pkgCache::DepIterator::IsCritical() const
578bfd0a 561{
359e46db 562 if (IsNegative() == true ||
71c9e95b
DK
563 S2->Type == pkgCache::Dep::Depends ||
564 S2->Type == pkgCache::Dep::PreDepends)
578bfd0a
AL
565 return true;
566 return false;
567}
568 /*}}}*/
df77d8a5
DK
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 */
573bool pkgCache::DepIterator::IsNegative() const
574{
71c9e95b
DK
575 return S2->Type == Dep::DpkgBreaks ||
576 S2->Type == Dep::Conflicts ||
577 S2->Type == Dep::Obsoletes;
df77d8a5
DK
578}
579 /*}}}*/
578bfd0a
AL
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
b2e465d6
AL
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. */
e841200b 593bool pkgCache::DepIterator::SmartTargetPkg(PkgIterator &Result) const
578bfd0a
AL
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();
f7f0d6c7 610 for (; PStart.end() != true && PStart.OwnerPkg() == ParentPkg(); ++PStart);
578bfd0a
AL
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;
f7f0d6c7 618 for (; P.end() != true; ++P)
578bfd0a
AL
619 {
620 // Skip over self provides
621 if (P.OwnerPkg() == ParentPkg())
622 continue;
623 if (PStart.OwnerPkg() != P.OwnerPkg())
624 break;
625 }
b2e465d6
AL
626
627 Result = PStart.OwnerPkg();
578bfd0a
AL
628
629 // Check for non dups
630 if (P.end() != true)
631 return true;
b2e465d6 632
578bfd0a
AL
633 return false;
634}
635 /*}}}*/
636// DepIterator::AllTargets - Returns the set of all possible targets /*{{{*/
637// ---------------------------------------------------------------------
b2e465d6 638/* This is a more useful version of TargetPkg() that follows versioned
578bfd0a 639 provides. It includes every possible package-version that could satisfy
fbfb2a7c
AL
640 the dependency. The last item in the list has a 0. The resulting pointer
641 must be delete [] 'd */
e841200b 642pkgCache::Version **pkgCache::DepIterator::AllTargets() const
578bfd0a
AL
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
f7f0d6c7 652 for (VerIterator I = DPkg.VersionList(); I.end() == false; ++I)
578bfd0a 653 {
85434114 654 if (IsIgnorable(I.ParentPkg()) == true)
578bfd0a 655 continue;
887c6940 656 if (IsSatisfied(I) == false)
578bfd0a 657 continue;
85434114 658
578bfd0a
AL
659 Size++;
660 if (Res != 0)
661 *End++ = I;
662 }
663
664 // Follow all provides
f7f0d6c7 665 for (PrvIterator I = DPkg.ProvidesList(); I.end() == false; ++I)
578bfd0a 666 {
85434114 667 if (IsIgnorable(I) == true)
578bfd0a 668 continue;
887c6940 669 if (IsSatisfied(I) == false)
85434114 670 continue;
5f909b67 671
578bfd0a
AL
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 /*}}}*/
43d017d6
AL
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. */
699void pkgCache::DepIterator::GlobOr(DepIterator &Start,DepIterator &End)
700{
701 // Compute a single dependency element (glob or)
702 Start = *this;
703 End = *this;
018f1533 704 for (bool LastOR = true; end() == false && LastOR == true;)
43d017d6 705 {
71c9e95b 706 LastOR = (S2->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or;
3707fd4f 707 ++(*this);
43d017d6
AL
708 if (LastOR == true)
709 End = (*this);
710 }
711}
712 /*}}}*/
85434114
DK
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. */
fd23676e 717bool pkgCache::DepIterator::IsIgnorable(PkgIterator const &PT) const
85434114 718{
021626db
DK
719 if (IsNegative() == false)
720 return false;
721
fd23676e 722 pkgCache::PkgIterator const PP = ParentPkg();
021626db
DK
723 if (PP->Group != PT->Group)
724 return false;
725 // self-conflict
726 if (PP == PT)
727 return true;
fd23676e 728 pkgCache::VerIterator const PV = ParentVer();
021626db
DK
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)
8c7af4d4 732 return IsMultiArchImplicit() == false;
85434114
DK
733
734 return false;
735}
736bool 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
8c7af4d4 747 if (IsMultiArchImplicit() && Prv.OwnerPkg()->Group != Pkg->Group)
85434114
DK
748 return true;
749
750 return false;
751}
752 /*}}}*/
887c6940
DK
753// DepIterator::IsSatisfied - check if a version satisfied the dependency /*{{{*/
754bool pkgCache::DepIterator::IsSatisfied(VerIterator const &Ver) const
755{
71c9e95b 756 return Owner->VS->CheckDep(Ver.VerStr(),S2->CompareOp,TargetVer());
887c6940
DK
757}
758bool pkgCache::DepIterator::IsSatisfied(PrvIterator const &Prv) const
759{
71c9e95b 760 return Owner->VS->CheckDep(Prv.ProvideVersion(),S2->CompareOp,TargetVer());
887c6940
DK
761}
762 /*}}}*/
8c7af4d4
DK
763// DepIterator::IsImplicit - added by the cache generation /*{{{*/
764bool 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 /*}}}*/
47f6d1b7
DK
777// ostream operator to handle string representation of a dependecy /*{{{*/
778// ---------------------------------------------------------------------
779/* */
8f3ba4e8 780std::ostream& operator<<(std::ostream& out, pkgCache::DepIterator D)
47f6d1b7
DK
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 /*}}}*/
578bfd0a
AL
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. */
805int 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;
f7f0d6c7 818 for (;I.end() == false; ++I)
578bfd0a
AL
819 if (I == B)
820 return 1;
821 return -1;
822}
823 /*}}}*/
b518cca6
AL
824// VerIterator::Downloadable - Checks if the version is downloadable /*{{{*/
825// ---------------------------------------------------------------------
826/* */
0e6fe58e 827APT_PURE bool pkgCache::VerIterator::Downloadable() const
b518cca6
AL
828{
829 VerFileIterator Files = FileList();
f7f0d6c7 830 for (; Files.end() == false; ++Files)
b07aeb1a 831 if (Files.File().Flagged(pkgCache::Flag::NotSource) == false)
b518cca6
AL
832 return true;
833 return false;
834}
835 /*}}}*/
3c124dde
AL
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. */
0e6fe58e 840APT_PURE bool pkgCache::VerIterator::Automatic() const
3c124dde
AL
841{
842 VerFileIterator Files = FileList();
f7f0d6c7 843 for (; Files.end() == false; ++Files)
5ed56f93 844 // Do not check ButAutomaticUpgrades here as it is kind of automatic…
b07aeb1a 845 if (Files.File().Flagged(pkgCache::Flag::NotAutomatic) == false)
3c124dde
AL
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.*/
854pkgCache::VerFileIterator pkgCache::VerIterator::NewestFile() const
855{
856 VerFileIterator Files = FileList();
857 VerFileIterator Highest = Files;
f7f0d6c7 858 for (; Files.end() == false; ++Files)
3c124dde 859 {
b2e465d6 860 if (Owner->VS->CmpReleaseVer(Files.File().Version(),Highest.File().Version()) > 0)
3c124dde
AL
861 Highest = Files;
862 }
863
864 return Highest;
865}
866 /*}}}*/
b2e465d6
AL
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 */
7f8c0eed
DK
871static 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}
d4489d49 894string pkgCache::VerIterator::RelStr() const
b2e465d6 895{
7f8c0eed 896 std::vector<std::string> RelStrs;
f7f0d6c7 897 for (pkgCache::VerFileIterator I = this->FileList(); I.end() == false; ++I)
b2e465d6
AL
898 {
899 // Do not print 'not source' entries'
b07aeb1a
DK
900 pkgCache::PkgFileIterator const File = I.File();
901 if (File.Flagged(pkgCache::Flag::NotSource))
b2e465d6
AL
902 continue;
903
7f8c0eed
DK
904 std::string const RS = PkgFileIteratorToRelString(File);
905 if (std::find(RelStrs.begin(), RelStrs.end(), RS) != RelStrs.end())
b2e465d6 906 continue;
b2e465d6 907
7f8c0eed
DK
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();
5dd4c8b8 915 }
857e9c13 916 if (S->ParentPkg != 0)
7f8c0eed
DK
917 os << " [" << Arch() << "]";
918 return os.str();
b2e465d6
AL
919}
920 /*}}}*/
7a948ec7
DK
921// VerIterator::MultiArchType - string representing MultiArch flag /*{{{*/
922const 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 /*}}}*/
b07aeb1a 933// RlsFileIterator::IsOk - Checks if the cache is in sync with the file /*{{{*/
578bfd0a
AL
934// ---------------------------------------------------------------------
935/* This stats the file and compares its stats with the ones that were
b07aeb1a 936 stored during generation. Date checks should probably also be
578bfd0a 937 included here. */
b07aeb1a 938bool pkgCache::RlsFileIterator::IsOk()
578bfd0a
AL
939{
940 struct stat Buf;
941 if (stat(FileName(),&Buf) != 0)
942 return false;
943
773e2c1f 944 if (Buf.st_size != (signed)S->Size || Buf.st_mtime != S->mtime)
578bfd0a
AL
945 return false;
946
947 return true;
948}
949 /*}}}*/
b07aeb1a
DK
950// RlsFileIterator::RelStr - Return the release string /*{{{*/
951string pkgCache::RlsFileIterator::RelStr()
af87ab54
AL
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();
efc487fb
DK
960 if (Codename() != 0)
961 Res = Res + (Res.empty() == true?"n=":",n=") + Codename();
af87ab54
AL
962 if (Label() != 0)
963 Res = Res + (Res.empty() == true?"l=":",l=") + Label();
b07aeb1a
DK
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. */
972bool 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 /*}}}*/
984string 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 }
5dd4c8b8
DK
998 if (Architecture() != 0)
999 Res = Res + (Res.empty() == true?"b=":",b=") + Architecture();
af87ab54
AL
1000 return Res;
1001}
1002 /*}}}*/
012b102a
MV
1003// VerIterator::TranslatedDescription - Return the a DescIter for locale/*{{{*/
1004// ---------------------------------------------------------------------
d3e8fbb3 1005/* return a DescIter for the current locale or the default if none is
012b102a
MV
1006 * found
1007 */
1008pkgCache::DescIterator pkgCache::VerIterator::TranslatedDescription() const
1009{
45df0ad2
DK
1010 std::vector<string> const lang = APT::Configuration::getLanguages();
1011 for (std::vector<string>::const_iterator l = lang.begin();
f7f0d6c7 1012 l != lang.end(); ++l)
45df0ad2 1013 {
4b625b95
DK
1014 pkgCache::DescIterator Desc = DescriptionList();
1015 for (; Desc.end() == false; ++Desc)
0e7c3313 1016 if (*l == Desc.LanguageCode())
45df0ad2 1017 break;
4b625b95 1018 if (Desc.end() == true)
0e7c3313
DK
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 }
45df0ad2
DK
1032 return Desc;
1033 }
4b625b95
DK
1034 for (pkgCache::DescIterator Desc = DescriptionList();
1035 Desc.end() == false; ++Desc)
1036 if (strcmp(Desc.LanguageCode(), "") == 0)
1037 return Desc;
45df0ad2 1038 return DescriptionList();
d3e8fbb3 1039}
012b102a
MV
1040
1041 /*}}}*/
c8a4ce6c
DK
1042
1043pkgCache::~pkgCache() {}