]> git.saurik.com Git - apt.git/blob - apt-pkg/pkgcache.cc
* merged from the apt--install-recommends branch
[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 managment. 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 #ifdef __GNUG__
24 #pragma implementation "apt-pkg/pkgcache.h"
25 #pragma implementation "apt-pkg/cacheiterators.h"
26 #endif
27
28 #include <apt-pkg/pkgcache.h>
29 #include <apt-pkg/indexfile.h>
30 #include <apt-pkg/version.h>
31 #include <apt-pkg/error.h>
32 #include <apt-pkg/strutl.h>
33 #include <apt-pkg/configuration.h>
34
35 #include <apti18n.h>
36
37 #include <string>
38 #include <sys/stat.h>
39 #include <unistd.h>
40
41 #include <ctype.h>
42 #include <system.h>
43 /*}}}*/
44
45 using std::string;
46
47
48 // Cache::Header::Header - Constructor /*{{{*/
49 // ---------------------------------------------------------------------
50 /* Simply initialize the header */
51 pkgCache::Header::Header()
52 {
53 Signature = 0x98FE76DC;
54
55 /* Whenever the structures change the major version should be bumped,
56 whenever the generator changes the minor version should be bumped. */
57 MajorVersion = 6;
58 MinorVersion = 0;
59 Dirty = false;
60
61 HeaderSz = sizeof(pkgCache::Header);
62 PackageSz = sizeof(pkgCache::Package);
63 PackageFileSz = sizeof(pkgCache::PackageFile);
64 VersionSz = sizeof(pkgCache::Version);
65 DescriptionSz = sizeof(pkgCache::Description);
66 DependencySz = sizeof(pkgCache::Dependency);
67 ProvidesSz = sizeof(pkgCache::Provides);
68 VerFileSz = sizeof(pkgCache::VerFile);
69 DescFileSz = sizeof(pkgCache::DescFile);
70
71 PackageCount = 0;
72 VersionCount = 0;
73 DescriptionCount = 0;
74 DependsCount = 0;
75 PackageFileCount = 0;
76 VerFileCount = 0;
77 DescFileCount = 0;
78 ProvidesCount = 0;
79 MaxVerFileSize = 0;
80 MaxDescFileSize = 0;
81
82 FileList = 0;
83 StringList = 0;
84 VerSysName = 0;
85 Architecture = 0;
86 memset(HashTable,0,sizeof(HashTable));
87 memset(Pools,0,sizeof(Pools));
88 }
89 /*}}}*/
90 // Cache::Header::CheckSizes - Check if the two headers have same *sz /*{{{*/
91 // ---------------------------------------------------------------------
92 /* */
93 bool pkgCache::Header::CheckSizes(Header &Against) const
94 {
95 if (HeaderSz == Against.HeaderSz &&
96 PackageSz == Against.PackageSz &&
97 PackageFileSz == Against.PackageFileSz &&
98 VersionSz == Against.VersionSz &&
99 DescriptionSz == Against.DescriptionSz &&
100 DependencySz == Against.DependencySz &&
101 VerFileSz == Against.VerFileSz &&
102 DescFileSz == Against.DescFileSz &&
103 ProvidesSz == Against.ProvidesSz)
104 return true;
105 return false;
106 }
107 /*}}}*/
108
109 // Cache::pkgCache - Constructor /*{{{*/
110 // ---------------------------------------------------------------------
111 /* */
112 pkgCache::pkgCache(MMap *Map, bool DoMap) : Map(*Map)
113 {
114 if (DoMap == true)
115 ReMap();
116 }
117 /*}}}*/
118 // Cache::ReMap - Reopen the cache file /*{{{*/
119 // ---------------------------------------------------------------------
120 /* If the file is already closed then this will open it open it. */
121 bool pkgCache::ReMap()
122 {
123 // Apply the typecasts.
124 HeaderP = (Header *)Map.Data();
125 PkgP = (Package *)Map.Data();
126 VerFileP = (VerFile *)Map.Data();
127 DescFileP = (DescFile *)Map.Data();
128 PkgFileP = (PackageFile *)Map.Data();
129 VerP = (Version *)Map.Data();
130 DescP = (Description *)Map.Data();
131 ProvideP = (Provides *)Map.Data();
132 DepP = (Dependency *)Map.Data();
133 StringItemP = (StringItem *)Map.Data();
134 StrP = (char *)Map.Data();
135
136 if (Map.Size() == 0 || HeaderP == 0)
137 return _error->Error(_("Empty package cache"));
138
139 // Check the header
140 Header DefHeader;
141 if (HeaderP->Signature != DefHeader.Signature ||
142 HeaderP->Dirty == true)
143 return _error->Error(_("The package cache file is corrupted"));
144
145 if (HeaderP->MajorVersion != DefHeader.MajorVersion ||
146 HeaderP->MinorVersion != DefHeader.MinorVersion ||
147 HeaderP->CheckSizes(DefHeader) == false)
148 return _error->Error(_("The package cache file is an incompatible version"));
149
150 // Locate our VS..
151 if (HeaderP->VerSysName == 0 ||
152 (VS = pkgVersioningSystem::GetVS(StrP + HeaderP->VerSysName)) == 0)
153 return _error->Error(_("This APT does not support the versioning system '%s'"),StrP + HeaderP->VerSysName);
154
155 // Chcek the arhcitecture
156 if (HeaderP->Architecture == 0 ||
157 _config->Find("APT::Architecture") != StrP + HeaderP->Architecture)
158 return _error->Error(_("The package cache was built for a different architecture"));
159 return true;
160 }
161 /*}}}*/
162 // Cache::Hash - Hash a string /*{{{*/
163 // ---------------------------------------------------------------------
164 /* This is used to generate the hash entries for the HashTable. With my
165 package list from bo this function gets 94% table usage on a 512 item
166 table (480 used items) */
167 unsigned long pkgCache::sHash(const string &Str) const
168 {
169 unsigned long Hash = 0;
170 for (string::const_iterator I = Str.begin(); I != Str.end(); I++)
171 Hash = 5*Hash + tolower(*I);
172 return Hash % _count(HeaderP->HashTable);
173 }
174
175 unsigned long pkgCache::sHash(const char *Str) const
176 {
177 unsigned long Hash = 0;
178 for (const char *I = Str; *I != 0; I++)
179 Hash = 5*Hash + tolower(*I);
180 return Hash % _count(HeaderP->HashTable);
181 }
182
183 /*}}}*/
184 // Cache::FindPkg - Locate a package by name /*{{{*/
185 // ---------------------------------------------------------------------
186 /* Returns 0 on error, pointer to the package otherwise */
187 pkgCache::PkgIterator pkgCache::FindPkg(const string &Name)
188 {
189 // Look at the hash bucket
190 Package *Pkg = PkgP + HeaderP->HashTable[Hash(Name)];
191 for (; Pkg != PkgP; Pkg = PkgP + Pkg->NextPackage)
192 {
193 if (Pkg->Name != 0 && StrP[Pkg->Name] == Name[0] &&
194 stringcasecmp(Name,StrP + Pkg->Name) == 0)
195 return PkgIterator(*this,Pkg);
196 }
197 return PkgIterator(*this,0);
198 }
199 /*}}}*/
200 // Cache::CompTypeDeb - Return a string describing the compare type /*{{{*/
201 // ---------------------------------------------------------------------
202 /* This returns a string representation of the dependency compare
203 type in the weird debian style.. */
204 const char *pkgCache::CompTypeDeb(unsigned char Comp)
205 {
206 const char *Ops[] = {"","<=",">=","<<",">>","=","!="};
207 if ((unsigned)(Comp & 0xF) < 7)
208 return Ops[Comp & 0xF];
209 return "";
210 }
211 /*}}}*/
212 // Cache::CompType - Return a string describing the compare type /*{{{*/
213 // ---------------------------------------------------------------------
214 /* This returns a string representation of the dependency compare
215 type */
216 const char *pkgCache::CompType(unsigned char Comp)
217 {
218 const char *Ops[] = {"","<=",">=","<",">","=","!="};
219 if ((unsigned)(Comp & 0xF) < 7)
220 return Ops[Comp & 0xF];
221 return "";
222 }
223 /*}}}*/
224 // Cache::DepType - Return a string describing the dep type /*{{{*/
225 // ---------------------------------------------------------------------
226 /* */
227 const char *pkgCache::DepType(unsigned char Type)
228 {
229 const char *Types[] = {"",_("Depends"),_("PreDepends"),_("Suggests"),
230 _("Recommends"),_("Conflicts"),_("Replaces"),
231 _("Obsoletes"),_("Breaks")};
232 if (Type < sizeof(Types)/sizeof(*Types))
233 return Types[Type];
234 return "";
235 }
236 /*}}}*/
237 // Cache::Priority - Convert a priority value to a string /*{{{*/
238 // ---------------------------------------------------------------------
239 /* */
240 const char *pkgCache::Priority(unsigned char Prio)
241 {
242 const char *Mapping[] = {0,_("important"),_("required"),_("standard"),
243 _("optional"),_("extra")};
244 if (Prio < _count(Mapping))
245 return Mapping[Prio];
246 return 0;
247 }
248 /*}}}*/
249 // Bases for iterator classes /*{{{*/
250 void pkgCache::VerIterator::_dummy() {}
251 void pkgCache::DepIterator::_dummy() {}
252 void pkgCache::PrvIterator::_dummy() {}
253 void pkgCache::DescIterator::_dummy() {}
254 /*}}}*/
255 // PkgIterator::operator ++ - Postfix incr /*{{{*/
256 // ---------------------------------------------------------------------
257 /* This will advance to the next logical package in the hash table. */
258 void pkgCache::PkgIterator::operator ++(int)
259 {
260 // Follow the current links
261 if (Pkg != Owner->PkgP)
262 Pkg = Owner->PkgP + Pkg->NextPackage;
263
264 // Follow the hash table
265 while (Pkg == Owner->PkgP && (HashIndex+1) < (signed)_count(Owner->HeaderP->HashTable))
266 {
267 HashIndex++;
268 Pkg = Owner->PkgP + Owner->HeaderP->HashTable[HashIndex];
269 }
270 };
271 /*}}}*/
272 // PkgIterator::State - Check the State of the package /*{{{*/
273 // ---------------------------------------------------------------------
274 /* By this we mean if it is either cleanly installed or cleanly removed. */
275 pkgCache::PkgIterator::OkState pkgCache::PkgIterator::State() const
276 {
277 if (Pkg->InstState == pkgCache::State::ReInstReq ||
278 Pkg->InstState == pkgCache::State::HoldReInstReq)
279 return NeedsUnpack;
280
281 if (Pkg->CurrentState == pkgCache::State::UnPacked ||
282 Pkg->CurrentState == pkgCache::State::HalfConfigured)
283 return NeedsConfigure;
284
285 if (Pkg->CurrentState == pkgCache::State::HalfInstalled ||
286 Pkg->InstState != pkgCache::State::Ok)
287 return NeedsUnpack;
288
289 return NeedsNothing;
290 }
291 /*}}}*/
292 // DepIterator::IsCritical - Returns true if the dep is important /*{{{*/
293 // ---------------------------------------------------------------------
294 /* Currently critical deps are defined as depends, predepends and
295 conflicts (including dpkg's Breaks fields). */
296 bool pkgCache::DepIterator::IsCritical()
297 {
298 if (Dep->Type == pkgCache::Dep::Conflicts ||
299 Dep->Type == pkgCache::Dep::DpkgBreaks ||
300 Dep->Type == pkgCache::Dep::Obsoletes ||
301 Dep->Type == pkgCache::Dep::Depends ||
302 Dep->Type == pkgCache::Dep::PreDepends)
303 return true;
304 return false;
305 }
306 /*}}}*/
307 // DepIterator::SmartTargetPkg - Resolve dep target pointers w/provides /*{{{*/
308 // ---------------------------------------------------------------------
309 /* This intellegently looks at dep target packages and tries to figure
310 out which package should be used. This is needed to nicely handle
311 provide mapping. If the target package has no other providing packages
312 then it returned. Otherwise the providing list is looked at to
313 see if there is one one unique providing package if so it is returned.
314 Otherwise true is returned and the target package is set. The return
315 result indicates whether the node should be expandable
316
317 In Conjunction with the DepCache the value of Result may not be
318 super-good since the policy may have made it uninstallable. Using
319 AllTargets is better in this case. */
320 bool pkgCache::DepIterator::SmartTargetPkg(PkgIterator &Result)
321 {
322 Result = TargetPkg();
323
324 // No provides at all
325 if (Result->ProvidesList == 0)
326 return false;
327
328 // There is the Base package and the providing ones which is at least 2
329 if (Result->VersionList != 0)
330 return true;
331
332 /* We have to skip over indirect provisions of the package that
333 owns the dependency. For instance, if libc5-dev depends on the
334 virtual package libc-dev which is provided by libc5-dev and libc6-dev
335 we must ignore libc5-dev when considering the provides list. */
336 PrvIterator PStart = Result.ProvidesList();
337 for (; PStart.end() != true && PStart.OwnerPkg() == ParentPkg(); PStart++);
338
339 // Nothing but indirect self provides
340 if (PStart.end() == true)
341 return false;
342
343 // Check for single packages in the provides list
344 PrvIterator P = PStart;
345 for (; P.end() != true; P++)
346 {
347 // Skip over self provides
348 if (P.OwnerPkg() == ParentPkg())
349 continue;
350 if (PStart.OwnerPkg() != P.OwnerPkg())
351 break;
352 }
353
354 Result = PStart.OwnerPkg();
355
356 // Check for non dups
357 if (P.end() != true)
358 return true;
359
360 return false;
361 }
362 /*}}}*/
363 // DepIterator::AllTargets - Returns the set of all possible targets /*{{{*/
364 // ---------------------------------------------------------------------
365 /* This is a more useful version of TargetPkg() that follows versioned
366 provides. It includes every possible package-version that could satisfy
367 the dependency. The last item in the list has a 0. The resulting pointer
368 must be delete [] 'd */
369 pkgCache::Version **pkgCache::DepIterator::AllTargets()
370 {
371 Version **Res = 0;
372 unsigned long Size =0;
373 while (1)
374 {
375 Version **End = Res;
376 PkgIterator DPkg = TargetPkg();
377
378 // Walk along the actual package providing versions
379 for (VerIterator I = DPkg.VersionList(); I.end() == false; I++)
380 {
381 if (Owner->VS->CheckDep(I.VerStr(),Dep->CompareOp,TargetVer()) == false)
382 continue;
383
384 if ((Dep->Type == pkgCache::Dep::Conflicts ||
385 Dep->Type == pkgCache::Dep::DpkgBreaks ||
386 Dep->Type == pkgCache::Dep::Obsoletes) &&
387 ParentPkg() == I.ParentPkg())
388 continue;
389
390 Size++;
391 if (Res != 0)
392 *End++ = I;
393 }
394
395 // Follow all provides
396 for (PrvIterator I = DPkg.ProvidesList(); I.end() == false; I++)
397 {
398 if (Owner->VS->CheckDep(I.ProvideVersion(),Dep->CompareOp,TargetVer()) == false)
399 continue;
400
401 if ((Dep->Type == pkgCache::Dep::Conflicts ||
402 Dep->Type == pkgCache::Dep::DpkgBreaks ||
403 Dep->Type == pkgCache::Dep::Obsoletes) &&
404 ParentPkg() == I.OwnerPkg())
405 continue;
406
407 Size++;
408 if (Res != 0)
409 *End++ = I.OwnerVer();
410 }
411
412 // Do it again and write it into the array
413 if (Res == 0)
414 {
415 Res = new Version *[Size+1];
416 Size = 0;
417 }
418 else
419 {
420 *End = 0;
421 break;
422 }
423 }
424
425 return Res;
426 }
427 /*}}}*/
428 // DepIterator::GlobOr - Compute an OR group /*{{{*/
429 // ---------------------------------------------------------------------
430 /* This Takes an iterator, iterates past the current dependency grouping
431 and returns Start and End so that so End is the final element
432 in the group, if End == Start then D is End++ and End is the
433 dependency D was pointing to. Use in loops to iterate sensibly. */
434 void pkgCache::DepIterator::GlobOr(DepIterator &Start,DepIterator &End)
435 {
436 // Compute a single dependency element (glob or)
437 Start = *this;
438 End = *this;
439 for (bool LastOR = true; end() == false && LastOR == true;)
440 {
441 LastOR = (Dep->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or;
442 (*this)++;
443 if (LastOR == true)
444 End = (*this);
445 }
446 }
447 /*}}}*/
448 // VerIterator::CompareVer - Fast version compare for same pkgs /*{{{*/
449 // ---------------------------------------------------------------------
450 /* This just looks over the version list to see if B is listed before A. In
451 most cases this will return in under 4 checks, ver lists are short. */
452 int pkgCache::VerIterator::CompareVer(const VerIterator &B) const
453 {
454 // Check if they are equal
455 if (*this == B)
456 return 0;
457 if (end() == true)
458 return -1;
459 if (B.end() == true)
460 return 1;
461
462 /* Start at A and look for B. If B is found then A > B otherwise
463 B was before A so A < B */
464 VerIterator I = *this;
465 for (;I.end() == false; I++)
466 if (I == B)
467 return 1;
468 return -1;
469 }
470 /*}}}*/
471 // VerIterator::Downloadable - Checks if the version is downloadable /*{{{*/
472 // ---------------------------------------------------------------------
473 /* */
474 bool pkgCache::VerIterator::Downloadable() const
475 {
476 VerFileIterator Files = FileList();
477 for (; Files.end() == false; Files++)
478 if ((Files.File()->Flags & pkgCache::Flag::NotSource) != pkgCache::Flag::NotSource)
479 return true;
480 return false;
481 }
482 /*}}}*/
483 // VerIterator::Automatic - Check if this version is 'automatic' /*{{{*/
484 // ---------------------------------------------------------------------
485 /* This checks to see if any of the versions files are not NotAutomatic.
486 True if this version is selectable for automatic installation. */
487 bool pkgCache::VerIterator::Automatic() const
488 {
489 VerFileIterator Files = FileList();
490 for (; Files.end() == false; Files++)
491 if ((Files.File()->Flags & pkgCache::Flag::NotAutomatic) != pkgCache::Flag::NotAutomatic)
492 return true;
493 return false;
494 }
495 /*}}}*/
496 // VerIterator::NewestFile - Return the newest file version relation /*{{{*/
497 // ---------------------------------------------------------------------
498 /* This looks at the version numbers associated with all of the sources
499 this version is in and returns the highest.*/
500 pkgCache::VerFileIterator pkgCache::VerIterator::NewestFile() const
501 {
502 VerFileIterator Files = FileList();
503 VerFileIterator Highest = Files;
504 for (; Files.end() == false; Files++)
505 {
506 if (Owner->VS->CmpReleaseVer(Files.File().Version(),Highest.File().Version()) > 0)
507 Highest = Files;
508 }
509
510 return Highest;
511 }
512 /*}}}*/
513 // VerIterator::RelStr - Release description string /*{{{*/
514 // ---------------------------------------------------------------------
515 /* This describes the version from a release-centric manner. The output is a
516 list of Label:Version/Archive */
517 string pkgCache::VerIterator::RelStr()
518 {
519 bool First = true;
520 string Res;
521 for (pkgCache::VerFileIterator I = this->FileList(); I.end() == false; I++)
522 {
523 // Do not print 'not source' entries'
524 pkgCache::PkgFileIterator File = I.File();
525 if ((File->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource)
526 continue;
527
528 // See if we have already printed this out..
529 bool Seen = false;
530 for (pkgCache::VerFileIterator J = this->FileList(); I != J; J++)
531 {
532 pkgCache::PkgFileIterator File2 = J.File();
533 if (File2->Label == 0 || File->Label == 0)
534 continue;
535
536 if (strcmp(File.Label(),File2.Label()) != 0)
537 continue;
538
539 if (File2->Version == File->Version)
540 {
541 Seen = true;
542 break;
543 }
544 if (File2->Version == 0 || File->Version == 0)
545 break;
546 if (strcmp(File.Version(),File2.Version()) == 0)
547 Seen = true;
548 }
549
550 if (Seen == true)
551 continue;
552
553 if (First == false)
554 Res += ", ";
555 else
556 First = false;
557
558 if (File->Label != 0)
559 Res = Res + File.Label() + ':';
560
561 if (File->Archive != 0)
562 {
563 if (File->Version == 0)
564 Res += File.Archive();
565 else
566 Res = Res + File.Version() + '/' + File.Archive();
567 }
568 else
569 {
570 // No release file, print the host name that this came from
571 if (File->Site == 0 || File.Site()[0] == 0)
572 Res += "localhost";
573 else
574 Res += File.Site();
575 }
576 }
577 return Res;
578 }
579 /*}}}*/
580 // PkgFileIterator::IsOk - Checks if the cache is in sync with the file /*{{{*/
581 // ---------------------------------------------------------------------
582 /* This stats the file and compares its stats with the ones that were
583 stored during generation. Date checks should probably also be
584 included here. */
585 bool pkgCache::PkgFileIterator::IsOk()
586 {
587 struct stat Buf;
588 if (stat(FileName(),&Buf) != 0)
589 return false;
590
591 if (Buf.st_size != (signed)File->Size || Buf.st_mtime != File->mtime)
592 return false;
593
594 return true;
595 }
596 /*}}}*/
597 // PkgFileIterator::RelStr - Return the release string /*{{{*/
598 // ---------------------------------------------------------------------
599 /* */
600 string pkgCache::PkgFileIterator::RelStr()
601 {
602 string Res;
603 if (Version() != 0)
604 Res = Res + (Res.empty() == true?"v=":",v=") + Version();
605 if (Origin() != 0)
606 Res = Res + (Res.empty() == true?"o=":",o=") + Origin();
607 if (Archive() != 0)
608 Res = Res + (Res.empty() == true?"a=":",a=") + Archive();
609 if (Label() != 0)
610 Res = Res + (Res.empty() == true?"l=":",l=") + Label();
611 if (Component() != 0)
612 Res = Res + (Res.empty() == true?"c=":",c=") + Component();
613 return Res;
614 }
615 /*}}}*/
616 // VerIterator::TranslatedDescription - Return the a DescIter for locale/*{{{*/
617 // ---------------------------------------------------------------------
618 /* return a DescIter for the current locale or the default if none is
619 * found
620 */
621 pkgCache::DescIterator pkgCache::VerIterator::TranslatedDescription() const
622 {
623 pkgCache::DescIterator DescDefault = DescriptionList();
624 pkgCache::DescIterator Desc = DescDefault;
625 for (; Desc.end() == false; Desc++)
626 if (pkgIndexFile::LanguageCode() == Desc.LanguageCode())
627 break;
628 if (Desc.end() == true) Desc = DescDefault;
629 return Desc;
630 };
631
632 /*}}}*/