]> git.saurik.com Git - apt.git/blob - apt-pkg/pkgcache.cc
* merged daniels wonderful doxygen work
[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 = 5;
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(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(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")};
232 if (Type < 8)
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. */
296 bool pkgCache::DepIterator::IsCritical()
297 {
298 if (Dep->Type == pkgCache::Dep::Conflicts ||
299 Dep->Type == pkgCache::Dep::Obsoletes ||
300 Dep->Type == pkgCache::Dep::Depends ||
301 Dep->Type == pkgCache::Dep::PreDepends)
302 return true;
303 return false;
304 }
305 /*}}}*/
306 // DepIterator::SmartTargetPkg - Resolve dep target pointers w/provides /*{{{*/
307 // ---------------------------------------------------------------------
308 /* This intellegently looks at dep target packages and tries to figure
309 out which package should be used. This is needed to nicely handle
310 provide mapping. If the target package has no other providing packages
311 then it returned. Otherwise the providing list is looked at to
312 see if there is one one unique providing package if so it is returned.
313 Otherwise true is returned and the target package is set. The return
314 result indicates whether the node should be expandable
315
316 In Conjunction with the DepCache the value of Result may not be
317 super-good since the policy may have made it uninstallable. Using
318 AllTargets is better in this case. */
319 bool pkgCache::DepIterator::SmartTargetPkg(PkgIterator &Result)
320 {
321 Result = TargetPkg();
322
323 // No provides at all
324 if (Result->ProvidesList == 0)
325 return false;
326
327 // There is the Base package and the providing ones which is at least 2
328 if (Result->VersionList != 0)
329 return true;
330
331 /* We have to skip over indirect provisions of the package that
332 owns the dependency. For instance, if libc5-dev depends on the
333 virtual package libc-dev which is provided by libc5-dev and libc6-dev
334 we must ignore libc5-dev when considering the provides list. */
335 PrvIterator PStart = Result.ProvidesList();
336 for (; PStart.end() != true && PStart.OwnerPkg() == ParentPkg(); PStart++);
337
338 // Nothing but indirect self provides
339 if (PStart.end() == true)
340 return false;
341
342 // Check for single packages in the provides list
343 PrvIterator P = PStart;
344 for (; P.end() != true; P++)
345 {
346 // Skip over self provides
347 if (P.OwnerPkg() == ParentPkg())
348 continue;
349 if (PStart.OwnerPkg() != P.OwnerPkg())
350 break;
351 }
352
353 Result = PStart.OwnerPkg();
354
355 // Check for non dups
356 if (P.end() != true)
357 return true;
358
359 return false;
360 }
361 /*}}}*/
362 // DepIterator::AllTargets - Returns the set of all possible targets /*{{{*/
363 // ---------------------------------------------------------------------
364 /* This is a more useful version of TargetPkg() that follows versioned
365 provides. It includes every possible package-version that could satisfy
366 the dependency. The last item in the list has a 0. The resulting pointer
367 must be delete [] 'd */
368 pkgCache::Version **pkgCache::DepIterator::AllTargets()
369 {
370 Version **Res = 0;
371 unsigned long Size =0;
372 while (1)
373 {
374 Version **End = Res;
375 PkgIterator DPkg = TargetPkg();
376
377 // Walk along the actual package providing versions
378 for (VerIterator I = DPkg.VersionList(); I.end() == false; I++)
379 {
380 if (Owner->VS->CheckDep(I.VerStr(),Dep->CompareOp,TargetVer()) == false)
381 continue;
382
383 if ((Dep->Type == pkgCache::Dep::Conflicts ||
384 Dep->Type == pkgCache::Dep::Obsoletes) &&
385 ParentPkg() == I.ParentPkg())
386 continue;
387
388 Size++;
389 if (Res != 0)
390 *End++ = I;
391 }
392
393 // Follow all provides
394 for (PrvIterator I = DPkg.ProvidesList(); I.end() == false; I++)
395 {
396 if (Owner->VS->CheckDep(I.ProvideVersion(),Dep->CompareOp,TargetVer()) == false)
397 continue;
398
399 if ((Dep->Type == pkgCache::Dep::Conflicts ||
400 Dep->Type == pkgCache::Dep::Obsoletes) &&
401 ParentPkg() == I.OwnerPkg())
402 continue;
403
404 Size++;
405 if (Res != 0)
406 *End++ = I.OwnerVer();
407 }
408
409 // Do it again and write it into the array
410 if (Res == 0)
411 {
412 Res = new Version *[Size+1];
413 Size = 0;
414 }
415 else
416 {
417 *End = 0;
418 break;
419 }
420 }
421
422 return Res;
423 }
424 /*}}}*/
425 // DepIterator::GlobOr - Compute an OR group /*{{{*/
426 // ---------------------------------------------------------------------
427 /* This Takes an iterator, iterates past the current dependency grouping
428 and returns Start and End so that so End is the final element
429 in the group, if End == Start then D is End++ and End is the
430 dependency D was pointing to. Use in loops to iterate sensibly. */
431 void pkgCache::DepIterator::GlobOr(DepIterator &Start,DepIterator &End)
432 {
433 // Compute a single dependency element (glob or)
434 Start = *this;
435 End = *this;
436 for (bool LastOR = true; end() == false && LastOR == true;)
437 {
438 LastOR = (Dep->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or;
439 (*this)++;
440 if (LastOR == true)
441 End = (*this);
442 }
443 }
444 /*}}}*/
445 // VerIterator::CompareVer - Fast version compare for same pkgs /*{{{*/
446 // ---------------------------------------------------------------------
447 /* This just looks over the version list to see if B is listed before A. In
448 most cases this will return in under 4 checks, ver lists are short. */
449 int pkgCache::VerIterator::CompareVer(const VerIterator &B) const
450 {
451 // Check if they are equal
452 if (*this == B)
453 return 0;
454 if (end() == true)
455 return -1;
456 if (B.end() == true)
457 return 1;
458
459 /* Start at A and look for B. If B is found then A > B otherwise
460 B was before A so A < B */
461 VerIterator I = *this;
462 for (;I.end() == false; I++)
463 if (I == B)
464 return 1;
465 return -1;
466 }
467 /*}}}*/
468 // VerIterator::Downloadable - Checks if the version is downloadable /*{{{*/
469 // ---------------------------------------------------------------------
470 /* */
471 bool pkgCache::VerIterator::Downloadable() const
472 {
473 VerFileIterator Files = FileList();
474 for (; Files.end() == false; Files++)
475 if ((Files.File()->Flags & pkgCache::Flag::NotSource) != pkgCache::Flag::NotSource)
476 return true;
477 return false;
478 }
479 /*}}}*/
480 // VerIterator::Automatic - Check if this version is 'automatic' /*{{{*/
481 // ---------------------------------------------------------------------
482 /* This checks to see if any of the versions files are not NotAutomatic.
483 True if this version is selectable for automatic installation. */
484 bool pkgCache::VerIterator::Automatic() const
485 {
486 VerFileIterator Files = FileList();
487 for (; Files.end() == false; Files++)
488 if ((Files.File()->Flags & pkgCache::Flag::NotAutomatic) != pkgCache::Flag::NotAutomatic)
489 return true;
490 return false;
491 }
492 /*}}}*/
493 // VerIterator::NewestFile - Return the newest file version relation /*{{{*/
494 // ---------------------------------------------------------------------
495 /* This looks at the version numbers associated with all of the sources
496 this version is in and returns the highest.*/
497 pkgCache::VerFileIterator pkgCache::VerIterator::NewestFile() const
498 {
499 VerFileIterator Files = FileList();
500 VerFileIterator Highest = Files;
501 for (; Files.end() == false; Files++)
502 {
503 if (Owner->VS->CmpReleaseVer(Files.File().Version(),Highest.File().Version()) > 0)
504 Highest = Files;
505 }
506
507 return Highest;
508 }
509 /*}}}*/
510 // VerIterator::RelStr - Release description string /*{{{*/
511 // ---------------------------------------------------------------------
512 /* This describes the version from a release-centric manner. The output is a
513 list of Label:Version/Archive */
514 string pkgCache::VerIterator::RelStr()
515 {
516 bool First = true;
517 string Res;
518 for (pkgCache::VerFileIterator I = this->FileList(); I.end() == false; I++)
519 {
520 // Do not print 'not source' entries'
521 pkgCache::PkgFileIterator File = I.File();
522 if ((File->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource)
523 continue;
524
525 // See if we have already printed this out..
526 bool Seen = false;
527 for (pkgCache::VerFileIterator J = this->FileList(); I != J; J++)
528 {
529 pkgCache::PkgFileIterator File2 = J.File();
530 if (File2->Label == 0 || File->Label == 0)
531 continue;
532
533 if (strcmp(File.Label(),File2.Label()) != 0)
534 continue;
535
536 if (File2->Version == File->Version)
537 {
538 Seen = true;
539 break;
540 }
541 if (File2->Version == 0 || File->Version == 0)
542 break;
543 if (strcmp(File.Version(),File2.Version()) == 0)
544 Seen = true;
545 }
546
547 if (Seen == true)
548 continue;
549
550 if (First == false)
551 Res += ", ";
552 else
553 First = false;
554
555 if (File->Label != 0)
556 Res = Res + File.Label() + ':';
557
558 if (File->Archive != 0)
559 {
560 if (File->Version == 0)
561 Res += File.Archive();
562 else
563 Res = Res + File.Version() + '/' + File.Archive();
564 }
565 else
566 {
567 // No release file, print the host name that this came from
568 if (File->Site == 0 || File.Site()[0] == 0)
569 Res += "localhost";
570 else
571 Res += File.Site();
572 }
573 }
574 return Res;
575 }
576 /*}}}*/
577 // PkgFileIterator::IsOk - Checks if the cache is in sync with the file /*{{{*/
578 // ---------------------------------------------------------------------
579 /* This stats the file and compares its stats with the ones that were
580 stored during generation. Date checks should probably also be
581 included here. */
582 bool pkgCache::PkgFileIterator::IsOk()
583 {
584 struct stat Buf;
585 if (stat(FileName(),&Buf) != 0)
586 return false;
587
588 if (Buf.st_size != (signed)File->Size || Buf.st_mtime != File->mtime)
589 return false;
590
591 return true;
592 }
593 /*}}}*/
594 // PkgFileIterator::RelStr - Return the release string /*{{{*/
595 // ---------------------------------------------------------------------
596 /* */
597 string pkgCache::PkgFileIterator::RelStr()
598 {
599 string Res;
600 if (Version() != 0)
601 Res = Res + (Res.empty() == true?"v=":",v=") + Version();
602 if (Origin() != 0)
603 Res = Res + (Res.empty() == true?"o=":",o=") + Origin();
604 if (Archive() != 0)
605 Res = Res + (Res.empty() == true?"a=":",a=") + Archive();
606 if (Label() != 0)
607 Res = Res + (Res.empty() == true?"l=":",l=") + Label();
608 if (Component() != 0)
609 Res = Res + (Res.empty() == true?"c=":",c=") + Component();
610 return Res;
611 }
612 /*}}}*/
613 // VerIterator::TranslatedDescription - Return the a DescIter for locale/*{{{*/
614 // ---------------------------------------------------------------------
615 /* return a DescIter for the current locale or the default if none is
616 * found
617 */
618 pkgCache::DescIterator pkgCache::VerIterator::TranslatedDescription() const
619 {
620 pkgCache::DescIterator DescDefault = DescriptionList();
621 pkgCache::DescIterator Desc = DescDefault;
622 for (; Desc.end() == false; Desc++)
623 if (pkgIndexFile::LanguageCode() == Desc.LanguageCode())
624 break;
625 if (Desc.end() == true) Desc = DescDefault;
626 return Desc;
627 };
628
629 /*}}}*/