]>
git.saurik.com Git - apt.git/blob - apt-pkg/pkgcache.cc
2a9756c453becc538fd89f444498873cf1cced2a
   1 // -*- mode: cpp; mode: fold -*- 
   3 // $Id: pkgcache.cc,v 1.37 2003/02/10 01:40:58 doogie Exp $ 
   4 /* ###################################################################### 
   6    Package Cache - Accessor code for the cache 
   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!! 
  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. 
  17    The main class provides for ways to get package indexes and some 
  18    general lookup functions to start the iterators. 
  20    ##################################################################### */ 
  22 // Include Files                                                        /*{{{*/ 
  23 #include <apt-pkg/pkgcache.h> 
  24 #include <apt-pkg/policy.h> 
  25 #include <apt-pkg/indexfile.h> 
  26 #include <apt-pkg/version.h> 
  27 #include <apt-pkg/error.h> 
  28 #include <apt-pkg/strutl.h> 
  29 #include <apt-pkg/configuration.h> 
  44 // Cache::Header::Header - Constructor                                  /*{{{*/ 
  45 // --------------------------------------------------------------------- 
  46 /* Simply initialize the header */ 
  47 pkgCache::Header::Header() 
  49    Signature 
= 0x98FE76DC; 
  51    /* Whenever the structures change the major version should be bumped, 
  52       whenever the generator changes the minor version should be bumped. */ 
  57    HeaderSz 
= sizeof(pkgCache::Header
); 
  58    PackageSz 
= sizeof(pkgCache::Package
); 
  59    PackageFileSz 
= sizeof(pkgCache::PackageFile
); 
  60    VersionSz 
= sizeof(pkgCache::Version
); 
  61    DescriptionSz 
= sizeof(pkgCache::Description
); 
  62    DependencySz 
= sizeof(pkgCache::Dependency
); 
  63    ProvidesSz 
= sizeof(pkgCache::Provides
); 
  64    VerFileSz 
= sizeof(pkgCache::VerFile
); 
  65    DescFileSz 
= sizeof(pkgCache::DescFile
); 
  82    memset(HashTable
,0,sizeof(HashTable
)); 
  83    memset(Pools
,0,sizeof(Pools
)); 
  86 // Cache::Header::CheckSizes - Check if the two headers have same *sz   /*{{{*/ 
  87 // --------------------------------------------------------------------- 
  89 bool pkgCache::Header::CheckSizes(Header 
&Against
) const 
  91    if (HeaderSz 
== Against
.HeaderSz 
&& 
  92        PackageSz 
== Against
.PackageSz 
&& 
  93        PackageFileSz 
== Against
.PackageFileSz 
&& 
  94        VersionSz 
== Against
.VersionSz 
&& 
  95        DescriptionSz 
== Against
.DescriptionSz 
&& 
  96        DependencySz 
== Against
.DependencySz 
&& 
  97        VerFileSz 
== Against
.VerFileSz 
&& 
  98        DescFileSz 
== Against
.DescFileSz 
&& 
  99        ProvidesSz 
== Against
.ProvidesSz
) 
 105 // Cache::pkgCache - Constructor                                        /*{{{*/ 
 106 // --------------------------------------------------------------------- 
 108 pkgCache::pkgCache(MMap 
*Map
, bool DoMap
) : Map(*Map
) 
 114 // Cache::ReMap - Reopen the cache file                                 /*{{{*/ 
 115 // --------------------------------------------------------------------- 
 116 /* If the file is already closed then this will open it open it. */ 
 117 bool pkgCache::ReMap() 
 119    // Apply the typecasts. 
 120    HeaderP 
= (Header 
*)Map
.Data(); 
 121    PkgP 
= (Package 
*)Map
.Data(); 
 122    VerFileP 
= (VerFile 
*)Map
.Data(); 
 123    DescFileP 
= (DescFile 
*)Map
.Data(); 
 124    PkgFileP 
= (PackageFile 
*)Map
.Data(); 
 125    VerP 
= (Version 
*)Map
.Data(); 
 126    DescP 
= (Description 
*)Map
.Data(); 
 127    ProvideP 
= (Provides 
*)Map
.Data(); 
 128    DepP 
= (Dependency 
*)Map
.Data(); 
 129    StringItemP 
= (StringItem 
*)Map
.Data(); 
 130    StrP 
= (char *)Map
.Data(); 
 132    if (Map
.Size() == 0 || HeaderP 
== 0) 
 133       return _error
->Error(_("Empty package cache")); 
 137    if (HeaderP
->Signature 
!= DefHeader
.Signature 
|| 
 138        HeaderP
->Dirty 
== true) 
 139       return _error
->Error(_("The package cache file is corrupted")); 
 141    if (HeaderP
->MajorVersion 
!= DefHeader
.MajorVersion 
|| 
 142        HeaderP
->MinorVersion 
!= DefHeader
.MinorVersion 
|| 
 143        HeaderP
->CheckSizes(DefHeader
) == false) 
 144       return _error
->Error(_("The package cache file is an incompatible version")); 
 147    if (HeaderP
->VerSysName 
== 0 || 
 148        (VS 
= pkgVersioningSystem::GetVS(StrP 
+ HeaderP
->VerSysName
)) == 0) 
 149       return _error
->Error(_("This APT does not support the versioning system '%s'"),StrP 
+ HeaderP
->VerSysName
); 
 151    // Chcek the arhcitecture 
 152    if (HeaderP
->Architecture 
== 0 || 
 153        _config
->Find("APT::Architecture") != StrP 
+ HeaderP
->Architecture
) 
 154       return _error
->Error(_("The package cache was built for a different architecture")); 
 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) */ 
 163 unsigned long pkgCache::sHash(const string 
&Str
) const 
 165    unsigned long Hash 
= 0; 
 166    for (string::const_iterator I 
= Str
.begin(); I 
!= Str
.end(); I
++) 
 167       Hash 
= 5*Hash 
+ tolower_ascii(*I
); 
 168    return Hash 
% _count(HeaderP
->HashTable
); 
 171 unsigned long pkgCache::sHash(const char *Str
) const 
 173    unsigned long Hash 
= 0; 
 174    for (const char *I 
= Str
; *I 
!= 0; I
++) 
 175       Hash 
= 5*Hash 
+ tolower_ascii(*I
); 
 176    return Hash 
% _count(HeaderP
->HashTable
); 
 180 // Cache::FindPkg - Locate a package by name                            /*{{{*/ 
 181 // --------------------------------------------------------------------- 
 182 /* Returns 0 on error, pointer to the package otherwise */ 
 183 pkgCache::PkgIterator 
pkgCache::FindPkg(const string 
&Name
) 
 185    // Look at the hash bucket 
 186    Package 
*Pkg 
= PkgP 
+ HeaderP
->HashTable
[Hash(Name
)]; 
 187    for (; Pkg 
!= PkgP
; Pkg 
= PkgP 
+ Pkg
->NextPackage
) 
 189       if (Pkg
->Name 
!= 0 && StrP
[Pkg
->Name
] == Name
[0] && 
 190           stringcasecmp(Name
,StrP 
+ Pkg
->Name
) == 0) 
 191          return PkgIterator(*this,Pkg
); 
 193    return PkgIterator(*this,0); 
 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.. */ 
 200 const char *pkgCache::CompTypeDeb(unsigned char Comp
) 
 202    const char *Ops
[] = {"","<=",">=","<<",">>","=","!="}; 
 203    if ((unsigned)(Comp 
& 0xF) < 7) 
 204       return Ops
[Comp 
& 0xF]; 
 208 // Cache::CompType - Return a string describing the compare type        /*{{{*/ 
 209 // --------------------------------------------------------------------- 
 210 /* This returns a string representation of the dependency compare  
 212 const char *pkgCache::CompType(unsigned char Comp
) 
 214    const char *Ops
[] = {"","<=",">=","<",">","=","!="}; 
 215    if ((unsigned)(Comp 
& 0xF) < 7) 
 216       return Ops
[Comp 
& 0xF]; 
 220 // Cache::DepType - Return a string describing the dep type             /*{{{*/ 
 221 // --------------------------------------------------------------------- 
 223 const char *pkgCache::DepType(unsigned char Type
) 
 225    const char *Types
[] = {"",_("Depends"),_("PreDepends"),_("Suggests"), 
 226                           _("Recommends"),_("Conflicts"),_("Replaces"), 
 227                           _("Obsoletes"),_("Breaks"), _("Enhances")}; 
 228    if (Type 
< sizeof(Types
)/sizeof(*Types
)) 
 233 // Cache::Priority - Convert a priority value to a string               /*{{{*/ 
 234 // --------------------------------------------------------------------- 
 236 const char *pkgCache::Priority(unsigned char Prio
) 
 238    const char *Mapping
[] = {0,_("important"),_("required"),_("standard"), 
 239                             _("optional"),_("extra")}; 
 240    if (Prio 
< _count(Mapping
)) 
 241       return Mapping
[Prio
]; 
 245 // Bases for iterator classes                                           /*{{{*/ 
 246 void pkgCache::VerIterator::_dummy() {} 
 247 void pkgCache::DepIterator::_dummy() {} 
 248 void pkgCache::PrvIterator::_dummy() {} 
 249 void pkgCache::DescIterator::_dummy() {} 
 251 // PkgIterator::operator ++ - Postfix incr                              /*{{{*/ 
 252 // --------------------------------------------------------------------- 
 253 /* This will advance to the next logical package in the hash table. */ 
 254 void pkgCache::PkgIterator::operator ++(int)  
 256    // Follow the current links 
 257    if (Pkg 
!= Owner
->PkgP
) 
 258       Pkg 
= Owner
->PkgP 
+ Pkg
->NextPackage
; 
 260    // Follow the hash table 
 261    while (Pkg 
== Owner
->PkgP 
&& (HashIndex
+1) < (signed)_count(Owner
->HeaderP
->HashTable
)) 
 264       Pkg 
= Owner
->PkgP 
+ Owner
->HeaderP
->HashTable
[HashIndex
]; 
 268 // PkgIterator::State - Check the State of the package                  /*{{{*/ 
 269 // --------------------------------------------------------------------- 
 270 /* By this we mean if it is either cleanly installed or cleanly removed. */ 
 271 pkgCache::PkgIterator::OkState 
pkgCache::PkgIterator::State() const 
 273    if (Pkg
->InstState 
== pkgCache::State::ReInstReq 
|| 
 274        Pkg
->InstState 
== pkgCache::State::HoldReInstReq
) 
 277    if (Pkg
->CurrentState 
== pkgCache::State::UnPacked 
|| 
 278        Pkg
->CurrentState 
== pkgCache::State::HalfConfigured 
|| 
 279       //we don't need to care for triggers awaiting packages 
 280       //dpkg will deal with them automatically when the  
 281       //trigger pending action is run (those packages are usually 
 282       //in half-configured or triggers-pending state) 
 283       //Pkg->CurrentState == pkgCache::State::TriggersAwaited 
 284        Pkg
->CurrentState 
== pkgCache::State::TriggersPending
) 
 285       return NeedsConfigure
; 
 287    if (Pkg
->CurrentState 
== pkgCache::State::HalfInstalled 
|| 
 288        Pkg
->InstState 
!= pkgCache::State::Ok
) 
 294 // PkgIterator::CandVersion - Returns the candidate version string      /*{{{*/ 
 295 // --------------------------------------------------------------------- 
 296 /* Return string representing of the candidate version. */ 
 298 pkgCache::PkgIterator::CandVersion() const  
 300   //TargetVer is empty, so don't use it. 
 301   VerIterator version 
= pkgPolicy::pkgPolicy(Owner
).GetCandidateVer(*this); 
 302   if (version
.IsGood()) 
 303     return version
.VerStr(); 
 307 // PkgIterator::CurVersion - Returns the current version string         /*{{{*/ 
 308 // --------------------------------------------------------------------- 
 309 /* Return string representing of the current version. */ 
 311 pkgCache::PkgIterator::CurVersion() const  
 313   VerIterator version 
= CurrentVer(); 
 314   if (version
.IsGood()) 
 315     return CurrentVer().VerStr(); 
 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. */ 
 326 operator<<(ostream
& out
, pkgCache::PkgIterator Pkg
)  
 328    if (Pkg
.end() == true) 
 329       return out 
<< "invalid package"; 
 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()); 
 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()) << " )"; 
 344 // DepIterator::IsCritical - Returns true if the dep is important       /*{{{*/ 
 345 // --------------------------------------------------------------------- 
 346 /* Currently critical deps are defined as depends, predepends and 
 347    conflicts (including dpkg's Breaks fields). */ 
 348 bool pkgCache::DepIterator::IsCritical() 
 350    if (Dep
->Type 
== pkgCache::Dep::Conflicts 
|| 
 351        Dep
->Type 
== pkgCache::Dep::DpkgBreaks 
|| 
 352        Dep
->Type 
== pkgCache::Dep::Obsoletes 
|| 
 353        Dep
->Type 
== pkgCache::Dep::Depends 
|| 
 354        Dep
->Type 
== pkgCache::Dep::PreDepends
) 
 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 
 367    result indicates whether the node should be expandable  
 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. */ 
 372 bool pkgCache::DepIterator::SmartTargetPkg(PkgIterator 
&Result
) 
 374    Result 
= TargetPkg(); 
 376    // No provides at all 
 377    if (Result
->ProvidesList 
== 0) 
 380    // There is the Base package and the providing ones which is at least 2 
 381    if (Result
->VersionList 
!= 0) 
 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
++); 
 391    // Nothing but indirect self provides 
 392    if (PStart
.end() == true) 
 395    // Check for single packages in the provides list 
 396    PrvIterator P 
= PStart
; 
 397    for (; P
.end() != true; P
++) 
 399       // Skip over self provides 
 400       if (P
.OwnerPkg() == ParentPkg()) 
 402       if (PStart
.OwnerPkg() != P
.OwnerPkg()) 
 406    Result 
= PStart
.OwnerPkg(); 
 408    // Check for non dups 
 415 // DepIterator::AllTargets - Returns the set of all possible targets    /*{{{*/ 
 416 // --------------------------------------------------------------------- 
 417 /* This is a more useful version of TargetPkg() that follows versioned 
 418    provides. It includes every possible package-version that could satisfy 
 419    the dependency. The last item in the list has a 0. The resulting pointer 
 420    must be delete [] 'd */ 
 421 pkgCache::Version 
**pkgCache::DepIterator::AllTargets() 
 424    unsigned long Size 
=0; 
 428       PkgIterator DPkg 
= TargetPkg(); 
 430       // Walk along the actual package providing versions 
 431       for (VerIterator I 
= DPkg
.VersionList(); I
.end() == false; I
++) 
 433          if (Owner
->VS
->CheckDep(I
.VerStr(),Dep
->CompareOp
,TargetVer()) == false) 
 436          if ((Dep
->Type 
== pkgCache::Dep::Conflicts 
|| 
 437               Dep
->Type 
== pkgCache::Dep::DpkgBreaks 
|| 
 438               Dep
->Type 
== pkgCache::Dep::Obsoletes
) && 
 439              ParentPkg() == I
.ParentPkg()) 
 447       // Follow all provides 
 448       for (PrvIterator I 
= DPkg
.ProvidesList(); I
.end() == false; I
++) 
 450          if (Owner
->VS
->CheckDep(I
.ProvideVersion(),Dep
->CompareOp
,TargetVer()) == false) 
 453          if ((Dep
->Type 
== pkgCache::Dep::Conflicts 
|| 
 454               Dep
->Type 
== pkgCache::Dep::DpkgBreaks 
|| 
 455               Dep
->Type 
== pkgCache::Dep::Obsoletes
) && 
 456              ParentPkg() == I
.OwnerPkg()) 
 461             *End
++ = I
.OwnerVer(); 
 464       // Do it again and write it into the array 
 467          Res 
= new Version 
*[Size
+1]; 
 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. */ 
 486 void pkgCache::DepIterator::GlobOr(DepIterator 
&Start
,DepIterator 
&End
) 
 488    // Compute a single dependency element (glob or) 
 491    for (bool LastOR 
= true; end() == false && LastOR 
== true;) 
 493       LastOR 
= (Dep
->CompareOp 
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
; 
 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. */ 
 504 int pkgCache::VerIterator::CompareVer(const VerIterator 
&B
) const 
 506    // Check if they are equal 
 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
++) 
 523 // VerIterator::Downloadable - Checks if the version is downloadable    /*{{{*/ 
 524 // --------------------------------------------------------------------- 
 526 bool pkgCache::VerIterator::Downloadable() const 
 528    VerFileIterator Files 
= FileList(); 
 529    for (; Files
.end() == false; Files
++) 
 530       if ((Files
.File()->Flags 
& pkgCache::Flag::NotSource
) != pkgCache::Flag::NotSource
) 
 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. */ 
 539 bool pkgCache::VerIterator::Automatic() const 
 541    VerFileIterator Files 
= FileList(); 
 542    for (; Files
.end() == false; Files
++) 
 543       if ((Files
.File()->Flags 
& pkgCache::Flag::NotAutomatic
) != pkgCache::Flag::NotAutomatic
) 
 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.*/ 
 552 pkgCache::VerFileIterator 
pkgCache::VerIterator::NewestFile() const 
 554    VerFileIterator Files 
= FileList(); 
 555    VerFileIterator Highest 
= Files
; 
 556    for (; Files
.end() == false; Files
++) 
 558       if (Owner
->VS
->CmpReleaseVer(Files
.File().Version(),Highest
.File().Version()) > 0) 
 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 */ 
 569 string 
pkgCache::VerIterator::RelStr() 
 573    for (pkgCache::VerFileIterator I 
= this->FileList(); I
.end() == false; I
++) 
 575       // Do not print 'not source' entries' 
 576       pkgCache::PkgFileIterator File 
= I
.File(); 
 577       if ((File
->Flags 
& pkgCache::Flag::NotSource
) == pkgCache::Flag::NotSource
) 
 580       // See if we have already printed this out.. 
 582       for (pkgCache::VerFileIterator J 
= this->FileList(); I 
!= J
; J
++) 
 584          pkgCache::PkgFileIterator File2 
= J
.File(); 
 585          if (File2
->Label 
== 0 || File
->Label 
== 0) 
 588          if (strcmp(File
.Label(),File2
.Label()) != 0) 
 591          if (File2
->Version 
== File
->Version
) 
 596          if (File2
->Version 
== 0 || File
->Version 
== 0) 
 598          if (strcmp(File
.Version(),File2
.Version()) == 0) 
 610       if (File
->Label 
!= 0) 
 611          Res 
= Res 
+ File
.Label() + ':'; 
 613       if (File
->Archive 
!= 0) 
 615          if (File
->Version 
== 0) 
 616             Res 
+= File
.Archive(); 
 618             Res 
= Res 
+ File
.Version() + '/' +  File
.Archive(); 
 622          // No release file, print the host name that this came from 
 623          if (File
->Site 
== 0 || File
.Site()[0] == 0) 
 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  
 637 bool pkgCache::PkgFileIterator::IsOk() 
 640    if (stat(FileName(),&Buf
) != 0) 
 643    if (Buf
.st_size 
!= (signed)File
->Size 
|| Buf
.st_mtime 
!= File
->mtime
) 
 649 // PkgFileIterator::RelStr - Return the release string                  /*{{{*/ 
 650 // --------------------------------------------------------------------- 
 652 string 
pkgCache::PkgFileIterator::RelStr() 
 656       Res 
= Res 
+ (Res
.empty() == true?"v=":",v=") + Version(); 
 658       Res 
= Res 
+ (Res
.empty() == true?"o=":",o=")  + Origin(); 
 660       Res 
= Res 
+ (Res
.empty() == true?"a=":",a=")  + Archive(); 
 662       Res 
= Res 
+ (Res
.empty() == true?"n=":",n=")  + Codename(); 
 664       Res 
= Res 
+ (Res
.empty() == true?"l=":",l=")  + Label(); 
 665    if (Component() != 0) 
 666       Res 
= Res 
+ (Res
.empty() == true?"c=":",c=")  + Component(); 
 670 // VerIterator::TranslatedDescription - Return the a DescIter for locale/*{{{*/ 
 671 // --------------------------------------------------------------------- 
 672 /* return a DescIter for the current locale or the default if none is  
 675 pkgCache::DescIterator 
pkgCache::VerIterator::TranslatedDescription() const 
 677    pkgCache::DescIterator DescDefault 
= DescriptionList(); 
 678    pkgCache::DescIterator Desc 
= DescDefault
; 
 679    for (; Desc
.end() == false; Desc
++) 
 680       if (pkgIndexFile::LanguageCode() == Desc
.LanguageCode()) 
 682    if (Desc
.end() == true)