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