1 // -*- mode: cpp; mode: fold -*- 
   3 // $Id: pkgcachegen.cc,v 1.53.2.1 2003/12/24 23:09:17 mdz Exp $ 
   4 /* ###################################################################### 
   6    Package Cache Generator - Generator for the cache structure. 
   8    This builds the cache structure from the abstract package list parser.  
  10    ##################################################################### */ 
  12 // Include Files                                                        /*{{{*/ 
  15 #include <apt-pkg/pkgcachegen.h> 
  16 #include <apt-pkg/error.h> 
  17 #include <apt-pkg/version.h> 
  18 #include <apt-pkg/progress.h> 
  19 #include <apt-pkg/sourcelist.h> 
  20 #include <apt-pkg/configuration.h> 
  21 #include <apt-pkg/pkgsystem.h> 
  22 #include <apt-pkg/macros.h> 
  23 #include <apt-pkg/metaindex.h> 
  24 #include <apt-pkg/fileutl.h> 
  25 #include <apt-pkg/hashsum_template.h> 
  26 #include <apt-pkg/indexfile.h> 
  27 #include <apt-pkg/md5.h> 
  28 #include <apt-pkg/mmap.h> 
  29 #include <apt-pkg/pkgcache.h> 
  30 #include <apt-pkg/cacheiterators.h> 
  44 template<class T
> using Dynamic 
= pkgCacheGenerator::Dynamic
<T
>;                                                        /*}}}*/ 
  45 typedef std::vector
<pkgIndexFile 
*>::iterator FileIterator
; 
  46 template <typename Iter
> std::vector
<Iter
*> pkgCacheGenerator::Dynamic
<Iter
>::toReMap
; 
  48 static bool IsDuplicateDescription(pkgCache::DescIterator Desc
, 
  49                             MD5SumValue 
const &CurMd5
, std::string 
const &CurLang
); 
  53 // CacheGenerator::pkgCacheGenerator - Constructor                      /*{{{*/ 
  54 // --------------------------------------------------------------------- 
  55 /* We set the dirty flag and make sure that is written to the disk */ 
  56 pkgCacheGenerator::pkgCacheGenerator(DynamicMMap 
*pMap
,OpProgress 
*Prog
) : 
  57                     Map(*pMap
), Cache(pMap
,false), Progress(Prog
), 
  58                      CurrentRlsFile(NULL
), CurrentFile(NULL
), d(NULL
) 
  62       // Setup the map interface.. 
  63       Cache
.HeaderP 
= (pkgCache::Header 
*)Map
.Data(); 
  64       _error
->PushToStack(); 
  65       Map
.RawAllocate(sizeof(pkgCache::Header
)); 
  66       bool const newError 
= _error
->PendingError(); 
  67       _error
->MergeWithStack(); 
  71       Map
.UsePools(*Cache
.HeaderP
->Pools
,sizeof(Cache
.HeaderP
->Pools
)/sizeof(Cache
.HeaderP
->Pools
[0])); 
  74       *Cache
.HeaderP 
= pkgCache::Header(); 
  76       // make room for the hashtables for packages and groups 
  77       if (Map
.RawAllocate(2 * (Cache
.HeaderP
->GetHashTableSize() * sizeof(map_pointer_t
))) == 0) 
  80       map_stringitem_t 
const idxVerSysName 
= WriteStringInMap(_system
->VS
->Label
); 
  81       if (unlikely(idxVerSysName 
== 0)) 
  83       Cache
.HeaderP
->VerSysName 
= idxVerSysName
; 
  84       map_stringitem_t 
const idxArchitecture 
= StoreString(MIXED
, _config
->Find("APT::Architecture")); 
  85       if (unlikely(idxArchitecture 
== 0)) 
  87       Cache
.HeaderP
->Architecture 
= idxArchitecture
; 
  89       std::vector
<std::string
> archs 
= APT::Configuration::getArchitectures(); 
  92          std::vector
<std::string
>::const_iterator a 
= archs
.begin(); 
  93          std::string list 
= *a
; 
  94          for (++a
; a 
!= archs
.end(); ++a
) 
  95             list
.append(",").append(*a
); 
  96          map_stringitem_t 
const idxArchitectures 
= WriteStringInMap(list
); 
  97          if (unlikely(idxArchitectures 
== 0)) 
  99          Cache
.HeaderP
->SetArchitectures(idxArchitectures
); 
 102          Cache
.HeaderP
->SetArchitectures(idxArchitecture
); 
 108       // Map directly from the existing file 
 110       Map
.UsePools(*Cache
.HeaderP
->Pools
,sizeof(Cache
.HeaderP
->Pools
)/sizeof(Cache
.HeaderP
->Pools
[0])); 
 111       if (Cache
.VS 
!= _system
->VS
) 
 113          _error
->Error(_("Cache has an incompatible versioning system")); 
 118    Cache
.HeaderP
->Dirty 
= true; 
 119    Map
.Sync(0,sizeof(pkgCache::Header
)); 
 122 // CacheGenerator::~pkgCacheGenerator - Destructor                      /*{{{*/ 
 123 // --------------------------------------------------------------------- 
 124 /* We sync the data then unset the dirty flag in two steps so as to 
 125    advoid a problem during a crash */ 
 126 pkgCacheGenerator::~pkgCacheGenerator() 
 128    if (_error
->PendingError() == true) 
 130    if (Map
.Sync() == false) 
 133    Cache
.HeaderP
->Dirty 
= false; 
 134    Cache
.HeaderP
->CacheFileSize 
= Map
.Size(); 
 135    Map
.Sync(0,sizeof(pkgCache::Header
)); 
 138 void pkgCacheGenerator::ReMap(void const * const oldMap
, void const * const newMap
) {/*{{{*/ 
 139    if (oldMap 
== newMap
) 
 142    if (_config
->FindB("Debug::pkgCacheGen", false)) 
 143       std::clog 
<< "Remaping from " << oldMap 
<< " to " << newMap 
<< std::endl
; 
 147    CurrentFile 
+= (pkgCache::PackageFile 
const * const) newMap 
- (pkgCache::PackageFile 
const * const) oldMap
; 
 148    CurrentRlsFile 
+= (pkgCache::ReleaseFile 
const * const) newMap 
- (pkgCache::ReleaseFile 
const * const) oldMap
; 
 150    for (std::vector
<pkgCache::GrpIterator
*>::const_iterator i 
= Dynamic
<pkgCache::GrpIterator
>::toReMap
.begin(); 
 151         i 
!= Dynamic
<pkgCache::GrpIterator
>::toReMap
.end(); ++i
) 
 152       (*i
)->ReMap(oldMap
, newMap
); 
 153    for (std::vector
<pkgCache::PkgIterator
*>::const_iterator i 
= Dynamic
<pkgCache::PkgIterator
>::toReMap
.begin(); 
 154         i 
!= Dynamic
<pkgCache::PkgIterator
>::toReMap
.end(); ++i
) 
 155       (*i
)->ReMap(oldMap
, newMap
); 
 156    for (std::vector
<pkgCache::VerIterator
*>::const_iterator i 
= Dynamic
<pkgCache::VerIterator
>::toReMap
.begin(); 
 157         i 
!= Dynamic
<pkgCache::VerIterator
>::toReMap
.end(); ++i
) 
 158       (*i
)->ReMap(oldMap
, newMap
); 
 159    for (std::vector
<pkgCache::DepIterator
*>::const_iterator i 
= Dynamic
<pkgCache::DepIterator
>::toReMap
.begin(); 
 160         i 
!= Dynamic
<pkgCache::DepIterator
>::toReMap
.end(); ++i
) 
 161       (*i
)->ReMap(oldMap
, newMap
); 
 162    for (std::vector
<pkgCache::DescIterator
*>::const_iterator i 
= Dynamic
<pkgCache::DescIterator
>::toReMap
.begin(); 
 163         i 
!= Dynamic
<pkgCache::DescIterator
>::toReMap
.end(); ++i
) 
 164       (*i
)->ReMap(oldMap
, newMap
); 
 165    for (std::vector
<pkgCache::PrvIterator
*>::const_iterator i 
= Dynamic
<pkgCache::PrvIterator
>::toReMap
.begin(); 
 166         i 
!= Dynamic
<pkgCache::PrvIterator
>::toReMap
.end(); ++i
) 
 167       (*i
)->ReMap(oldMap
, newMap
); 
 168    for (std::vector
<pkgCache::PkgFileIterator
*>::const_iterator i 
= Dynamic
<pkgCache::PkgFileIterator
>::toReMap
.begin(); 
 169         i 
!= Dynamic
<pkgCache::PkgFileIterator
>::toReMap
.end(); ++i
) 
 170       (*i
)->ReMap(oldMap
, newMap
); 
 171    for (std::vector
<pkgCache::RlsFileIterator
*>::const_iterator i 
= Dynamic
<pkgCache::RlsFileIterator
>::toReMap
.begin(); 
 172         i 
!= Dynamic
<pkgCache::RlsFileIterator
>::toReMap
.end(); ++i
) 
 173       (*i
)->ReMap(oldMap
, newMap
); 
 175 // CacheGenerator::WriteStringInMap                                     /*{{{*/ 
 176 map_stringitem_t 
pkgCacheGenerator::WriteStringInMap(const char *String
, 
 177                                         const unsigned long &Len
) { 
 178    void const * const oldMap 
= Map
.Data(); 
 179    map_stringitem_t 
const index 
= Map
.WriteString(String
, Len
); 
 181       ReMap(oldMap
, Map
.Data()); 
 185 // CacheGenerator::WriteStringInMap                                     /*{{{*/ 
 186 map_stringitem_t 
pkgCacheGenerator::WriteStringInMap(const char *String
) { 
 187    void const * const oldMap 
= Map
.Data(); 
 188    map_stringitem_t 
const index 
= Map
.WriteString(String
); 
 190       ReMap(oldMap
, Map
.Data()); 
 194 map_pointer_t 
pkgCacheGenerator::AllocateInMap(const unsigned long &size
) {/*{{{*/ 
 195    void const * const oldMap 
= Map
.Data(); 
 196    map_pointer_t 
const index 
= Map
.Allocate(size
); 
 198       ReMap(oldMap
, Map
.Data()); 
 202 // CacheGenerator::MergeList - Merge the package list                   /*{{{*/ 
 203 // --------------------------------------------------------------------- 
 204 /* This provides the generation of the entries in the cache. Each loop 
 205    goes through a single package record from the underlying parse engine. */ 
 206 bool pkgCacheGenerator::MergeList(ListParser 
&List
, 
 207                                   pkgCache::VerIterator 
*OutVer
) 
 211    unsigned int Counter 
= 0; 
 212    while (List
.Step() == true) 
 214       string 
const PackageName 
= List
.Package(); 
 215       if (PackageName
.empty() == true) 
 219       if (Counter 
% 100 == 0 && Progress 
!= 0) 
 220          Progress
->Progress(List
.Offset()); 
 222       string Arch 
= List
.Architecture(); 
 223       string 
const Version 
= List
.Version(); 
 224       if (Version
.empty() == true && Arch
.empty() == true) 
 226          // package descriptions 
 227          if (MergeListGroup(List
, PackageName
) == false) 
 232       // Get a pointer to the package structure 
 233       pkgCache::PkgIterator Pkg
; 
 234       Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
); 
 235       if (NewPackage(Pkg
, PackageName
, Arch
) == false) 
 236          // TRANSLATOR: The first placeholder is a package name, 
 237          // the other two should be copied verbatim as they include debug info 
 238          return _error
->Error(_("Error occurred while processing %s (%s%d)"), 
 239                               PackageName
.c_str(), "NewPackage", 1); 
 242       if (Version
.empty() == true) 
 244          if (MergeListPackage(List
, Pkg
) == false) 
 249          if (MergeListVersion(List
, Pkg
, Version
, OutVer
) == false) 
 257    if (Cache
.HeaderP
->PackageCount 
>= std::numeric_limits
<map_id_t
>::max()) 
 258       return _error
->Error(_("Wow, you exceeded the number of package " 
 259                              "names this APT is capable of.")); 
 260    if (Cache
.HeaderP
->VersionCount 
>= std::numeric_limits
<map_id_t
>::max()) 
 261       return _error
->Error(_("Wow, you exceeded the number of versions " 
 262                              "this APT is capable of.")); 
 263    if (Cache
.HeaderP
->DescriptionCount 
>= std::numeric_limits
<map_id_t
>::max()) 
 264       return _error
->Error(_("Wow, you exceeded the number of descriptions " 
 265                              "this APT is capable of.")); 
 266    if (Cache
.HeaderP
->DependsCount 
>= std::numeric_limits
<map_id_t
>::max()) 
 267       return _error
->Error(_("Wow, you exceeded the number of dependencies " 
 268                              "this APT is capable of.")); 
 272 // CacheGenerator::MergeListGroup                                       /*{{{*/ 
 273 bool pkgCacheGenerator::MergeListGroup(ListParser 
&List
, std::string 
const &GrpName
) 
 275    pkgCache::GrpIterator Grp 
= Cache
.FindGrp(GrpName
); 
 276    // a group has no data on it's own, only packages have it but these 
 277    // stanzas like this come from Translation- files to add descriptions, 
 278    // but without a version we don't need a description for it… 
 279    if (Grp
.end() == true) 
 281    Dynamic
<pkgCache::GrpIterator
> DynGrp(Grp
); 
 283    pkgCache::PkgIterator Pkg
; 
 284    Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
); 
 285    for (Pkg 
= Grp
.PackageList(); Pkg
.end() == false; Pkg 
= Grp
.NextPkg(Pkg
)) 
 286       if (MergeListPackage(List
, Pkg
) == false) 
 292 // CacheGenerator::MergeListPackage                                     /*{{{*/ 
 293 bool pkgCacheGenerator::MergeListPackage(ListParser 
&List
, pkgCache::PkgIterator 
&Pkg
) 
 295    // we first process the package, then the descriptions 
 296    // (for deb this package processing is in fact a no-op) 
 297    pkgCache::VerIterator 
Ver(Cache
); 
 298    Dynamic
<pkgCache::VerIterator
> DynVer(Ver
); 
 299    if (List
.UsePackage(Pkg
, Ver
) == false) 
 300       return _error
->Error(_("Error occurred while processing %s (%s%d)"), 
 301                            Pkg
.Name(), "UsePackage", 1); 
 303    // Find the right version to write the description 
 304    MD5SumValue CurMd5 
= List
.Description_md5(); 
 305    if (CurMd5
.Value().empty() == true && List
.Description("").empty() == true) 
 307    std::vector
<std::string
> availDesc 
= List
.AvailableDescriptionLanguages(); 
 308    for (Ver 
= Pkg
.VersionList(); Ver
.end() == false; ++Ver
) 
 310       pkgCache::DescIterator VerDesc 
= Ver
.DescriptionList(); 
 312       // a version can only have one md5 describing it 
 313       if (VerDesc
.end() == true || MD5SumValue(VerDesc
.md5()) != CurMd5
) 
 316       map_stringitem_t md5idx 
= VerDesc
->md5sum
; 
 317       for (std::vector
<std::string
>::const_iterator CurLang 
= availDesc
.begin(); CurLang 
!= availDesc
.end(); ++CurLang
) 
 319          // don't add a new description if we have one for the given 
 321          if (IsDuplicateDescription(VerDesc
, CurMd5
, *CurLang
) == true) 
 324          AddNewDescription(List
, Ver
, *CurLang
, CurMd5
, md5idx
); 
 327       // we can stop here as all "same" versions will share the description 
 334 // CacheGenerator::MergeListVersion                                     /*{{{*/ 
 335 bool pkgCacheGenerator::MergeListVersion(ListParser 
&List
, pkgCache::PkgIterator 
&Pkg
, 
 336                                          std::string 
const &Version
, pkgCache::VerIterator
* &OutVer
) 
 338    pkgCache::VerIterator Ver 
= Pkg
.VersionList(); 
 339    Dynamic
<pkgCache::VerIterator
> DynVer(Ver
); 
 340    map_pointer_t 
*LastVer 
= &Pkg
->VersionList
; 
 341    void const * oldMap 
= Map
.Data(); 
 343    unsigned short const Hash 
= List
.VersionHash(); 
 344    if (Ver
.end() == false) 
 346       /* We know the list is sorted so we use that fact in the search. 
 347          Insertion of new versions is done with correct sorting */ 
 349       for (; Ver
.end() == false; LastVer 
= &Ver
->NextVer
, ++Ver
) 
 351          Res 
= Cache
.VS
->CmpVersion(Version
,Ver
.VerStr()); 
 352          // Version is higher as current version - insert here 
 355          // Versionstrings are equal - is hash also equal? 
 356          if (Res 
== 0 && List
.SameVersion(Hash
, Ver
) == true) 
 358          // proceed with the next till we have either the right 
 359          // or we found another version (which will be lower) 
 362       /* We already have a version for this item, record that we saw it */ 
 363       if (Res 
== 0 && Ver
.end() == false && Ver
->Hash 
== Hash
) 
 365          if (List
.UsePackage(Pkg
,Ver
) == false) 
 366             return _error
->Error(_("Error occurred while processing %s (%s%d)"), 
 367                                  Pkg
.Name(), "UsePackage", 2); 
 369          if (NewFileVer(Ver
,List
) == false) 
 370             return _error
->Error(_("Error occurred while processing %s (%s%d)"), 
 371                                  Pkg
.Name(), "NewFileVer", 1); 
 373          // Read only a single record and return 
 385    map_pointer_t 
const verindex 
= NewVersion(Ver
, Version
, Pkg
.Index(), Hash
, *LastVer
); 
 386    if (unlikely(verindex 
== 0)) 
 387       return _error
->Error(_("Error occurred while processing %s (%s%d)"), 
 388                            Pkg
.Name(), "NewVersion", 1); 
 390    if (oldMap 
!= Map
.Data()) 
 391          LastVer 
+= (map_pointer_t 
const * const) Map
.Data() - (map_pointer_t 
const * const) oldMap
; 
 394    if (unlikely(List
.NewVersion(Ver
) == false)) 
 395       return _error
->Error(_("Error occurred while processing %s (%s%d)"), 
 396                            Pkg
.Name(), "NewVersion", 2); 
 398    if (unlikely(List
.UsePackage(Pkg
,Ver
) == false)) 
 399       return _error
->Error(_("Error occurred while processing %s (%s%d)"), 
 400                            Pkg
.Name(), "UsePackage", 3); 
 402    if (unlikely(NewFileVer(Ver
,List
) == false)) 
 403       return _error
->Error(_("Error occurred while processing %s (%s%d)"), 
 404                            Pkg
.Name(), "NewFileVer", 2); 
 406    pkgCache::GrpIterator Grp 
= Pkg
.Group(); 
 407    Dynamic
<pkgCache::GrpIterator
> DynGrp(Grp
); 
 409    /* If it is the first version of this package we need to add implicit 
 410       Multi-Arch dependencies to all other package versions in the group now - 
 411       otherwise we just add them for this new version */ 
 412    if (Pkg
.VersionList()->NextVer 
== 0) 
 414       pkgCache::PkgIterator P 
= Grp
.PackageList(); 
 415       Dynamic
<pkgCache::PkgIterator
> DynP(P
); 
 416       for (; P
.end() != true; P 
= Grp
.NextPkg(P
)) 
 418          if (P
->ID 
== Pkg
->ID
) 
 420          pkgCache::VerIterator V 
= P
.VersionList(); 
 421          Dynamic
<pkgCache::VerIterator
> DynV(V
); 
 422          for (; V
.end() != true; ++V
) 
 423             if (unlikely(AddImplicitDepends(V
, Pkg
) == false)) 
 424                return _error
->Error(_("Error occurred while processing %s (%s%d)"), 
 425                                     Pkg
.Name(), "AddImplicitDepends", 1); 
 428    if (unlikely(AddImplicitDepends(Grp
, Pkg
, Ver
) == false)) 
 429       return _error
->Error(_("Error occurred while processing %s (%s%d)"), 
 430                            Pkg
.Name(), "AddImplicitDepends", 2); 
 432    // Read only a single record and return 
 439    /* Record the Description(s) based on their master md5sum */ 
 440    MD5SumValue CurMd5 
= List
.Description_md5(); 
 441    if (CurMd5
.Value().empty() == true && List
.Description("").empty() == true) 
 444    /* Before we add a new description we first search in the group for 
 445       a version with a description of the same MD5 - if so we reuse this 
 446       description group instead of creating our own for this version */ 
 447    for (pkgCache::PkgIterator P 
= Grp
.PackageList(); 
 448         P
.end() == false; P 
= Grp
.NextPkg(P
)) 
 450       for (pkgCache::VerIterator V 
= P
.VersionList(); 
 451            V
.end() == false; ++V
) 
 453          if (V
->DescriptionList 
== 0 || MD5SumValue(V
.DescriptionList().md5()) != CurMd5
) 
 455          Ver
->DescriptionList 
= V
->DescriptionList
; 
 459    // We haven't found reusable descriptions, so add the first description(s) 
 460    map_stringitem_t md5idx 
= Ver
->DescriptionList 
== 0 ? 0 : Ver
.DescriptionList()->md5sum
; 
 461    std::vector
<std::string
> availDesc 
= List
.AvailableDescriptionLanguages(); 
 462    for (std::vector
<std::string
>::const_iterator CurLang 
= availDesc
.begin(); CurLang 
!= availDesc
.end(); ++CurLang
) 
 463       if (AddNewDescription(List
, Ver
, *CurLang
, CurMd5
, md5idx
) == false) 
 468 bool pkgCacheGenerator::AddNewDescription(ListParser 
&List
, pkgCache::VerIterator 
&Ver
, std::string 
const &lang
, MD5SumValue 
const &CurMd5
, map_stringitem_t 
&md5idx
) /*{{{*/ 
 470    pkgCache::DescIterator Desc
; 
 471    Dynamic
<pkgCache::DescIterator
> DynDesc(Desc
); 
 473    map_pointer_t 
const descindex 
= NewDescription(Desc
, lang
, CurMd5
, md5idx
); 
 474    if (unlikely(descindex 
== 0)) 
 475       return _error
->Error(_("Error occurred while processing %s (%s%d)"), 
 476             Ver
.ParentPkg().Name(), "NewDescription", 1); 
 478    md5idx 
= Desc
->md5sum
; 
 479    Desc
->ParentPkg 
= Ver
.ParentPkg().Index(); 
 481    // we add at the end, so that the start is constant as we need 
 482    // that to be able to efficiently share these lists 
 483    pkgCache::DescIterator VerDesc 
= Ver
.DescriptionList(); // old value might be invalid after ReMap 
 484    for (;VerDesc
.end() == false && VerDesc
->NextDesc 
!= 0; ++VerDesc
); 
 485    map_pointer_t 
* const LastNextDesc 
= (VerDesc
.end() == true) ? &Ver
->DescriptionList 
: &VerDesc
->NextDesc
; 
 486    *LastNextDesc 
= descindex
; 
 488    if (NewFileDesc(Desc
,List
) == false) 
 489       return _error
->Error(_("Error occurred while processing %s (%s%d)"), 
 490             Ver
.ParentPkg().Name(), "NewFileDesc", 1); 
 496 // CacheGenerator::NewGroup - Add a new group                           /*{{{*/ 
 497 // --------------------------------------------------------------------- 
 498 /* This creates a new group structure and adds it to the hash table */ 
 499 bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator 
&Grp
, const string 
&Name
) 
 501    Grp 
= Cache
.FindGrp(Name
); 
 502    if (Grp
.end() == false) 
 506    map_pointer_t 
const Group 
= AllocateInMap(sizeof(pkgCache::Group
)); 
 507    if (unlikely(Group 
== 0)) 
 510    Grp 
= pkgCache::GrpIterator(Cache
, Cache
.GrpP 
+ Group
); 
 511    map_stringitem_t 
const idxName 
= StoreString(PKGNAME
, Name
); 
 512    if (unlikely(idxName 
== 0)) 
 516    // Insert it into the hash table 
 517    unsigned long const Hash 
= Cache
.Hash(Name
); 
 518    map_pointer_t 
*insertAt 
= &Cache
.HeaderP
->GrpHashTableP()[Hash
]; 
 519    while (*insertAt 
!= 0 && strcasecmp(Name
.c_str(), Cache
.StrP 
+ (Cache
.GrpP 
+ *insertAt
)->Name
) > 0) 
 520       insertAt 
= &(Cache
.GrpP 
+ *insertAt
)->Next
; 
 521    Grp
->Next 
= *insertAt
; 
 524    Grp
->ID 
= Cache
.HeaderP
->GroupCount
++; 
 528 // CacheGenerator::NewPackage - Add a new package                       /*{{{*/ 
 529 // --------------------------------------------------------------------- 
 530 /* This creates a new package structure and adds it to the hash table */ 
 531 bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator 
&Pkg
,const string 
&Name
, 
 532                                         const string 
&Arch
) { 
 533    pkgCache::GrpIterator Grp
; 
 534    Dynamic
<pkgCache::GrpIterator
> DynGrp(Grp
); 
 535    if (unlikely(NewGroup(Grp
, Name
) == false)) 
 538    Pkg 
= Grp
.FindPkg(Arch
); 
 539       if (Pkg
.end() == false) 
 543    map_pointer_t 
const Package 
= AllocateInMap(sizeof(pkgCache::Package
)); 
 544    if (unlikely(Package 
== 0)) 
 546    Pkg 
= pkgCache::PkgIterator(Cache
,Cache
.PkgP 
+ Package
); 
 548    // Set the name, arch and the ID 
 549    APT_IGNORE_DEPRECATED(Pkg
->Name 
= Grp
->Name
;) 
 550    Pkg
->Group 
= Grp
.Index(); 
 551    // all is mapped to the native architecture 
 552    map_stringitem_t 
const idxArch 
= (Arch 
== "all") ? Cache
.HeaderP
->Architecture 
: StoreString(MIXED
, Arch
); 
 553    if (unlikely(idxArch 
== 0)) 
 556    Pkg
->ID 
= Cache
.HeaderP
->PackageCount
++; 
 558    // Insert the package into our package list 
 559    if (Grp
->FirstPackage 
== 0) // the group is new 
 561       Grp
->FirstPackage 
= Package
; 
 562       // Insert it into the hash table 
 563       map_id_t 
const Hash 
= Cache
.Hash(Name
); 
 564       map_pointer_t 
*insertAt 
= &Cache
.HeaderP
->PkgHashTableP()[Hash
]; 
 565       while (*insertAt 
!= 0 && strcasecmp(Name
.c_str(), Cache
.StrP 
+ (Cache
.GrpP 
+ (Cache
.PkgP 
+ *insertAt
)->Group
)->Name
) > 0) 
 566          insertAt 
= &(Cache
.PkgP 
+ *insertAt
)->NextPackage
; 
 567       Pkg
->NextPackage 
= *insertAt
; 
 570    else // Group the Packages together 
 572       // but first get implicit provides done 
 573       if (APT::Configuration::checkArchitecture(Pkg
.Arch()) == true) 
 575          pkgCache::PkgIterator 
const M 
= Grp
.FindPreferredPkg(false); // native or any foreign pkg will do 
 576          if (M
.end() == false) { 
 577             pkgCache::PrvIterator Prv
; 
 578             Dynamic
<pkgCache::PrvIterator
> DynPrv(Prv
); 
 579             for (Prv 
= M
.ProvidesList(); Prv
.end() == false; ++Prv
) 
 581                if ((Prv
->Flags 
& pkgCache::Flag::ArchSpecific
) != 0) 
 583                pkgCache::VerIterator Ver 
= Prv
.OwnerVer(); 
 584                Dynamic
<pkgCache::VerIterator
> DynVer(Ver
); 
 585                if ((Ver
->MultiArch 
& pkgCache::Version::Allowed
) == pkgCache::Version::Allowed 
|| 
 586                    ((Ver
->MultiArch 
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign 
&& 
 587                         (Prv
->Flags 
& pkgCache::Flag::MultiArchImplicit
) == 0)) 
 588                   if (NewProvides(Ver
, Pkg
, Prv
->ProvideVersion
, Prv
->Flags
) == false) 
 594          pkgCache::PkgIterator P
; 
 595          pkgCache::VerIterator Ver
; 
 596          Dynamic
<pkgCache::PkgIterator
> DynP(P
); 
 597          Dynamic
<pkgCache::VerIterator
> DynVer(Ver
); 
 599          for (P 
= Grp
.PackageList(); P
.end() == false;  P 
= Grp
.NextPkg(P
)) 
 600             for (Ver 
= P
.VersionList(); Ver
.end() == false; ++Ver
) 
 601                if ((Ver
->MultiArch 
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
) 
 602                   if (NewProvides(Ver
, Pkg
, Ver
->VerStr
, pkgCache::Flag::MultiArchImplicit
) == false) 
 605       // and negative dependencies, don't forget negative dependencies 
 607          pkgCache::PkgIterator 
const M 
= Grp
.FindPreferredPkg(false); 
 608          if (M
.end() == false) { 
 609             pkgCache::DepIterator Dep
; 
 610             Dynamic
<pkgCache::DepIterator
> DynDep(Dep
); 
 611             for (Dep 
= M
.RevDependsList(); Dep
.end() == false; ++Dep
) 
 613                if ((Dep
->CompareOp 
& (pkgCache::Dep::ArchSpecific 
| pkgCache::Dep::MultiArchImplicit
)) != 0) 
 615                if (Dep
->Type 
!= pkgCache::Dep::DpkgBreaks 
&& Dep
->Type 
!= pkgCache::Dep::Conflicts 
&& 
 616                      Dep
->Type 
!= pkgCache::Dep::Replaces
) 
 618                pkgCache::VerIterator Ver 
= Dep
.ParentVer(); 
 619                Dynamic
<pkgCache::VerIterator
> DynVer(Ver
); 
 620                map_pointer_t 
* unused 
= NULL
; 
 621                if (NewDepends(Pkg
, Ver
, Dep
->Version
, Dep
->CompareOp
, Dep
->Type
, unused
) == false) 
 627       // this package is the new last package 
 628       pkgCache::PkgIterator 
LastPkg(Cache
, Cache
.PkgP 
+ Grp
->LastPackage
); 
 629       Pkg
->NextPackage 
= LastPkg
->NextPackage
; 
 630       LastPkg
->NextPackage 
= Package
; 
 632    Grp
->LastPackage 
= Package
; 
 634    // lazy-create foo (of amd64) provides foo:amd64 at the time we first need it 
 637       size_t const found 
= Name
.find(':'); 
 638       std::string 
const NameA 
= Name
.substr(0, found
); 
 639       std::string 
const ArchA 
= Name
.substr(found 
+ 1); 
 640       pkgCache::PkgIterator PkgA 
= Cache
.FindPkg(NameA
, ArchA
); 
 641       if (PkgA
.end() == false) 
 643          Dynamic
<pkgCache::PkgIterator
> DynPkgA(PkgA
); 
 644          pkgCache::PrvIterator Prv 
= PkgA
.ProvidesList(); 
 645          for (; Prv
.end() == false; ++Prv
) 
 647             if (Prv
.IsMultiArchImplicit()) 
 649             pkgCache::VerIterator V 
= Prv
.OwnerVer(); 
 650             if (ArchA 
!= V
.ParentPkg().Arch()) 
 652             if (NewProvides(V
, Pkg
, V
->VerStr
, pkgCache::Flag::MultiArchImplicit 
| pkgCache::Flag::ArchSpecific
) == false) 
 655          pkgCache::VerIterator V 
= PkgA
.VersionList(); 
 656          Dynamic
<pkgCache::VerIterator
> DynV(V
); 
 657          for (; V
.end() == false; ++V
) 
 659             if (NewProvides(V
, Pkg
, V
->VerStr
, pkgCache::Flag::MultiArchImplicit 
| pkgCache::Flag::ArchSpecific
) == false) 
 667 // CacheGenerator::AddImplicitDepends                                   /*{{{*/ 
 668 bool pkgCacheGenerator::AddImplicitDepends(pkgCache::GrpIterator 
&G
, 
 669                                            pkgCache::PkgIterator 
&P
, 
 670                                            pkgCache::VerIterator 
&V
) 
 672    // copy P.Arch() into a string here as a cache remap 
 673    // in NewDepends() later may alter the pointer location 
 674    string Arch 
= P
.Arch() == NULL 
? "" : P
.Arch(); 
 675    map_pointer_t 
*OldDepLast 
= NULL
; 
 676    /* MultiArch handling introduces a lot of implicit Dependencies: 
 677       - MultiArch: same → Co-Installable if they have the same version 
 678       - All others conflict with all other group members */ 
 679    bool const coInstall 
= ((V
->MultiArch 
& pkgCache::Version::Same
) == pkgCache::Version::Same
); 
 680    pkgCache::PkgIterator D 
= G
.PackageList(); 
 681    Dynamic
<pkgCache::PkgIterator
> DynD(D
); 
 682    map_stringitem_t 
const VerStrIdx 
= V
->VerStr
; 
 683    for (; D
.end() != true; D 
= G
.NextPkg(D
)) 
 685       if (Arch 
== D
.Arch() || D
->VersionList 
== 0) 
 687       /* We allow only one installed arch at the time 
 688          per group, therefore each group member conflicts 
 689          with all other group members */ 
 690       if (coInstall 
== true) 
 692          // Replaces: ${self}:other ( << ${binary:Version}) 
 693          NewDepends(D
, V
, VerStrIdx
, 
 694                     pkgCache::Dep::Less 
| pkgCache::Dep::MultiArchImplicit
, pkgCache::Dep::Replaces
, 
 696          // Breaks: ${self}:other (!= ${binary:Version}) 
 697          NewDepends(D
, V
, VerStrIdx
, 
 698                     pkgCache::Dep::NotEquals 
| pkgCache::Dep::MultiArchImplicit
, pkgCache::Dep::DpkgBreaks
, 
 701          // Conflicts: ${self}:other 
 703                     pkgCache::Dep::NoOp 
| pkgCache::Dep::MultiArchImplicit
, pkgCache::Dep::Conflicts
, 
 709 bool pkgCacheGenerator::AddImplicitDepends(pkgCache::VerIterator 
&V
, 
 710                                            pkgCache::PkgIterator 
&D
) 
 712    /* MultiArch handling introduces a lot of implicit Dependencies: 
 713       - MultiArch: same → Co-Installable if they have the same version 
 714       - All others conflict with all other group members */ 
 715    map_pointer_t 
*OldDepLast 
= NULL
; 
 716    bool const coInstall 
= ((V
->MultiArch 
& pkgCache::Version::Same
) == pkgCache::Version::Same
); 
 717    if (coInstall 
== true) 
 719       map_stringitem_t 
const VerStrIdx 
= V
->VerStr
; 
 720       // Replaces: ${self}:other ( << ${binary:Version}) 
 721       NewDepends(D
, V
, VerStrIdx
, 
 722                  pkgCache::Dep::Less 
| pkgCache::Dep::MultiArchImplicit
, pkgCache::Dep::Replaces
, 
 724       // Breaks: ${self}:other (!= ${binary:Version}) 
 725       NewDepends(D
, V
, VerStrIdx
, 
 726                  pkgCache::Dep::NotEquals 
| pkgCache::Dep::MultiArchImplicit
, pkgCache::Dep::DpkgBreaks
, 
 729       // Conflicts: ${self}:other 
 731                  pkgCache::Dep::NoOp 
| pkgCache::Dep::MultiArchImplicit
, pkgCache::Dep::Conflicts
, 
 738 // CacheGenerator::NewFileVer - Create a new File<->Version association /*{{{*/ 
 739 // --------------------------------------------------------------------- 
 741 bool pkgCacheGenerator::NewFileVer(pkgCache::VerIterator 
&Ver
, 
 744    if (CurrentFile 
== 0) 
 748    map_pointer_t 
const VerFile 
= AllocateInMap(sizeof(pkgCache::VerFile
)); 
 752    pkgCache::VerFileIterator 
VF(Cache
,Cache
.VerFileP 
+ VerFile
); 
 753    VF
->File 
= CurrentFile 
- Cache
.PkgFileP
; 
 755    // Link it to the end of the list 
 756    map_pointer_t 
*Last 
= &Ver
->FileList
; 
 757    for (pkgCache::VerFileIterator V 
= Ver
.FileList(); V
.end() == false; ++V
) 
 759    VF
->NextFile 
= *Last
; 
 762    VF
->Offset 
= List
.Offset(); 
 763    VF
->Size 
= List
.Size(); 
 764    if (Cache
.HeaderP
->MaxVerFileSize 
< VF
->Size
) 
 765       Cache
.HeaderP
->MaxVerFileSize 
= VF
->Size
; 
 766    Cache
.HeaderP
->VerFileCount
++; 
 771 // CacheGenerator::NewVersion - Create a new Version                    /*{{{*/ 
 772 // --------------------------------------------------------------------- 
 773 /* This puts a version structure in the linked list */ 
 774 map_pointer_t 
pkgCacheGenerator::NewVersion(pkgCache::VerIterator 
&Ver
, 
 775                                             const string 
&VerStr
, 
 776                                             map_pointer_t 
const ParentPkg
, 
 777                                             unsigned short const Hash
, 
 778                                             map_pointer_t 
const Next
) 
 781    map_pointer_t 
const Version 
= AllocateInMap(sizeof(pkgCache::Version
)); 
 786    Ver 
= pkgCache::VerIterator(Cache
,Cache
.VerP 
+ Version
); 
 787    //Dynamic<pkgCache::VerIterator> DynV(Ver); // caller MergeListVersion already takes care of it 
 789    Ver
->ParentPkg 
= ParentPkg
; 
 791    Ver
->ID 
= Cache
.HeaderP
->VersionCount
++; 
 793    // try to find the version string in the group for reuse 
 794    pkgCache::PkgIterator Pkg 
= Ver
.ParentPkg(); 
 795    pkgCache::GrpIterator Grp 
= Pkg
.Group(); 
 796    if (Pkg
.end() == false && Grp
.end() == false) 
 798       for (pkgCache::PkgIterator P 
= Grp
.PackageList(); P
.end() == false; P 
= Grp
.NextPkg(P
)) 
 802          for (pkgCache::VerIterator V 
= P
.VersionList(); V
.end() == false; ++V
) 
 804             int const cmp 
= strcmp(V
.VerStr(), VerStr
.c_str()); 
 807                Ver
->VerStr 
= V
->VerStr
; 
 815    // haven't found the version string, so create 
 816    map_stringitem_t 
const idxVerStr 
= StoreString(VERSIONNUMBER
, VerStr
); 
 817    if (unlikely(idxVerStr 
== 0)) 
 819    Ver
->VerStr 
= idxVerStr
; 
 823 // CacheGenerator::NewFileDesc - Create a new File<->Desc association   /*{{{*/ 
 824 // --------------------------------------------------------------------- 
 826 bool pkgCacheGenerator::NewFileDesc(pkgCache::DescIterator 
&Desc
, 
 829    if (CurrentFile 
== 0) 
 833    map_pointer_t 
const DescFile 
= AllocateInMap(sizeof(pkgCache::DescFile
)); 
 837    pkgCache::DescFileIterator 
DF(Cache
,Cache
.DescFileP 
+ DescFile
); 
 838    DF
->File 
= CurrentFile 
- Cache
.PkgFileP
; 
 840    // Link it to the end of the list 
 841    map_pointer_t 
*Last 
= &Desc
->FileList
; 
 842    for (pkgCache::DescFileIterator D 
= Desc
.FileList(); D
.end() == false; ++D
) 
 845    DF
->NextFile 
= *Last
; 
 848    DF
->Offset 
= List
.Offset(); 
 849    DF
->Size 
= List
.Size(); 
 850    if (Cache
.HeaderP
->MaxDescFileSize 
< DF
->Size
) 
 851       Cache
.HeaderP
->MaxDescFileSize 
= DF
->Size
; 
 852    Cache
.HeaderP
->DescFileCount
++; 
 857 // CacheGenerator::NewDescription - Create a new Description            /*{{{*/ 
 858 // --------------------------------------------------------------------- 
 859 /* This puts a description structure in the linked list */ 
 860 map_pointer_t 
pkgCacheGenerator::NewDescription(pkgCache::DescIterator 
&Desc
, 
 862                                             const MD5SumValue 
&md5sum
, 
 863                                             map_stringitem_t 
const idxmd5str
) 
 866    map_pointer_t 
const Description 
= AllocateInMap(sizeof(pkgCache::Description
)); 
 867    if (Description 
== 0) 
 871    Desc 
= pkgCache::DescIterator(Cache
,Cache
.DescP 
+ Description
); 
 872    Desc
->ID 
= Cache
.HeaderP
->DescriptionCount
++; 
 873    map_stringitem_t 
const idxlanguage_code 
= StoreString(MIXED
, Lang
); 
 874    if (unlikely(idxlanguage_code 
== 0)) 
 876    Desc
->language_code 
= idxlanguage_code
; 
 879       Desc
->md5sum 
= idxmd5str
; 
 882       map_stringitem_t 
const idxmd5sum 
= WriteStringInMap(md5sum
.Value()); 
 883       if (unlikely(idxmd5sum 
== 0)) 
 885       Desc
->md5sum 
= idxmd5sum
; 
 891 // CacheGenerator::NewDepends - Create a dependency element             /*{{{*/ 
 892 // --------------------------------------------------------------------- 
 893 /* This creates a dependency element in the tree. It is linked to the 
 894    version and to the package that it is pointing to. */ 
 895 bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator 
&Pkg
, 
 896                                    pkgCache::VerIterator 
&Ver
, 
 897                                    map_pointer_t 
const Version
, 
 900                                    map_pointer_t
* &OldDepLast
) 
 902    void const * const oldMap 
= Map
.Data(); 
 904    map_pointer_t 
const Dependency 
= AllocateInMap(sizeof(pkgCache::Dependency
)); 
 905    if (unlikely(Dependency 
== 0)) 
 908    bool isDuplicate 
= false; 
 909    map_pointer_t DependencyData 
= 0; 
 910    map_pointer_t PreviousData 
= 0; 
 911    if (Pkg
->RevDepends 
!= 0) 
 913       pkgCache::Dependency 
const * const L 
= Cache
.DepP 
+ Pkg
->RevDepends
; 
 914       DependencyData 
= L
->DependencyData
; 
 916          pkgCache::DependencyData 
const * const D 
= Cache
.DepDataP 
+ DependencyData
; 
 917          if (Version 
> D
->Version
) 
 919          if (D
->Version 
== Version 
&& D
->Type 
== Type 
&& D
->CompareOp 
== Op
) 
 924          PreviousData 
= DependencyData
; 
 925          DependencyData 
= D
->NextData
; 
 926       } while (DependencyData 
!= 0); 
 929    if (isDuplicate 
== false) 
 931       DependencyData 
= AllocateInMap(sizeof(pkgCache::DependencyData
)); 
 932       if (unlikely(DependencyData 
== 0)) 
 936    pkgCache::Dependency 
* Link 
= Cache
.DepP 
+ Dependency
; 
 937    Link
->ParentVer 
= Ver
.Index(); 
 938    Link
->DependencyData 
= DependencyData
; 
 939    Link
->ID 
= Cache
.HeaderP
->DependsCount
++; 
 941    pkgCache::DepIterator 
Dep(Cache
, Link
); 
 942    if (isDuplicate 
== false) 
 946       Dep
->Version 
= Version
; 
 947       Dep
->Package 
= Pkg
.Index(); 
 948       ++Cache
.HeaderP
->DependsDataCount
; 
 949       if (PreviousData 
!= 0) 
 951          pkgCache::DependencyData 
* const D 
= Cache
.DepDataP 
+ PreviousData
; 
 952          Dep
->NextData 
= D
->NextData
; 
 953          D
->NextData 
= DependencyData
; 
 955       else if (Pkg
->RevDepends 
!= 0) 
 957          pkgCache::Dependency 
const * const D 
= Cache
.DepP 
+ Pkg
->RevDepends
; 
 958          Dep
->NextData 
= D
->DependencyData
; 
 962    if (isDuplicate 
== true || PreviousData 
!= 0) 
 964       pkgCache::Dependency 
* const L 
= Cache
.DepP 
+ Pkg
->RevDepends
; 
 965       Link
->NextRevDepends 
= L
->NextRevDepends
; 
 966       L
->NextRevDepends 
= Dependency
; 
 970       Link
->NextRevDepends 
= Pkg
->RevDepends
; 
 971       Pkg
->RevDepends 
= Dependency
; 
 975    // Do we know where to link the Dependency to? 
 976    if (OldDepLast 
== NULL
) 
 978       OldDepLast 
= &Ver
->DependsList
; 
 979       for (pkgCache::DepIterator D 
= Ver
.DependsList(); D
.end() == false; ++D
) 
 980          OldDepLast 
= &D
->NextDepends
; 
 981    } else if (oldMap 
!= Map
.Data()) 
 982       OldDepLast 
+= (map_pointer_t 
const * const) Map
.Data() - (map_pointer_t 
const * const) oldMap
; 
 984    Dep
->NextDepends 
= *OldDepLast
; 
 985    *OldDepLast 
= Dependency
; 
 986    OldDepLast 
= &Dep
->NextDepends
; 
 990 // ListParser::NewDepends - Create the environment for a new dependency /*{{{*/ 
 991 // --------------------------------------------------------------------- 
 992 /* This creates a Group and the Package to link this dependency to if 
 993    needed and handles also the caching of the old endpoint */ 
 994 bool pkgCacheListParser::NewDepends(pkgCache::VerIterator 
&Ver
, 
 995                                                const string 
&PackageName
, 
 997                                                const string 
&Version
, 
1001    pkgCache::GrpIterator Grp
; 
1002    Dynamic
<pkgCache::GrpIterator
> DynGrp(Grp
); 
1003    if (unlikely(Owner
->NewGroup(Grp
, PackageName
) == false)) 
1006    map_stringitem_t idxVersion 
= 0; 
1007    if (Version
.empty() == false) 
1009       int const CmpOp 
= Op 
& 0x0F; 
1010       // =-deps are used (79:1) for lockstep on same-source packages (e.g. data-packages) 
1011       if (CmpOp 
== pkgCache::Dep::Equals 
&& strcmp(Version
.c_str(), Ver
.VerStr()) == 0) 
1012          idxVersion 
= Ver
->VerStr
; 
1014       if (idxVersion 
== 0) 
1016          idxVersion 
= StoreString(pkgCacheGenerator::VERSIONNUMBER
, Version
); 
1017          if (unlikely(idxVersion 
== 0)) 
1022    bool const isNegative 
= (Type 
== pkgCache::Dep::DpkgBreaks 
|| 
1023          Type 
== pkgCache::Dep::Conflicts 
|| 
1024          Type 
== pkgCache::Dep::Replaces
); 
1026    pkgCache::PkgIterator Pkg
; 
1027    Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
); 
1028    if (isNegative 
== false || (Op 
& pkgCache::Dep::ArchSpecific
) == pkgCache::Dep::ArchSpecific 
|| Grp
->FirstPackage 
== 0) 
1030       // Locate the target package 
1031       Pkg 
= Grp
.FindPkg(Arch
); 
1032       if (Pkg
.end() == true) { 
1033          if (unlikely(Owner
->NewPackage(Pkg
, PackageName
, Arch
) == false)) 
1037       /* Caching the old end point speeds up generation substantially */ 
1038       if (OldDepVer 
!= Ver
) { 
1043       return Owner
->NewDepends(Pkg
, Ver
, idxVersion
, Op
, Type
, OldDepLast
); 
1047       /* Caching the old end point speeds up generation substantially */ 
1048       if (OldDepVer 
!= Ver
) { 
1053       for (Pkg 
= Grp
.PackageList(); Pkg
.end() == false; Pkg 
= Grp
.NextPkg(Pkg
)) 
1055          if (Owner
->NewDepends(Pkg
, Ver
, idxVersion
, Op
, Type
, OldDepLast
) == false) 
1062 // ListParser::NewProvides - Create a Provides element                  /*{{{*/ 
1063 bool pkgCacheListParser::NewProvides(pkgCache::VerIterator 
&Ver
, 
1064                                                 const string 
&PkgName
, 
1065                                                 const string 
&PkgArch
, 
1066                                                 const string 
&Version
, 
1067                                                 uint8_t const Flags
) 
1069    pkgCache 
const &Cache 
= Owner
->Cache
; 
1071    // We do not add self referencing provides 
1072    if (Ver
.ParentPkg().Name() == PkgName 
&& (PkgArch 
== Ver
.ParentPkg().Arch() || 
1073         (PkgArch 
== "all" && strcmp((Cache
.StrP 
+ Cache
.HeaderP
->Architecture
), Ver
.ParentPkg().Arch()) == 0))) 
1076    // Locate the target package 
1077    pkgCache::PkgIterator Pkg
; 
1078    Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
); 
1079    if (unlikely(Owner
->NewPackage(Pkg
,PkgName
, PkgArch
) == false)) 
1082    map_stringitem_t idxProvideVersion 
= 0; 
1083    if (Version
.empty() == false) { 
1084       idxProvideVersion 
= StoreString(pkgCacheGenerator::VERSIONNUMBER
, Version
); 
1085       if (unlikely(idxProvideVersion 
== 0)) 
1088    return Owner
->NewProvides(Ver
, Pkg
, idxProvideVersion
, Flags
); 
1090 bool pkgCacheGenerator::NewProvides(pkgCache::VerIterator 
&Ver
, 
1091                                     pkgCache::PkgIterator 
&Pkg
, 
1092                                     map_pointer_t 
const ProvideVersion
, 
1093                                     uint8_t const Flags
) 
1096    map_pointer_t 
const Provides 
= AllocateInMap(sizeof(pkgCache::Provides
)); 
1097    if (unlikely(Provides 
== 0)) 
1099    ++Cache
.HeaderP
->ProvidesCount
; 
1102    pkgCache::PrvIterator 
Prv(Cache
,Cache
.ProvideP 
+ Provides
,Cache
.PkgP
); 
1103    Prv
->Version 
= Ver
.Index(); 
1104    Prv
->ProvideVersion 
= ProvideVersion
; 
1106    Prv
->NextPkgProv 
= Ver
->ProvidesList
; 
1107    Ver
->ProvidesList 
= Prv
.Index(); 
1109    // Link it to the package 
1110    Prv
->ParentPkg 
= Pkg
.Index(); 
1111    Prv
->NextProvides 
= Pkg
->ProvidesList
; 
1112    Pkg
->ProvidesList 
= Prv
.Index(); 
1116 // ListParser::NewProvidesAllArch - add provides for all architectures  /*{{{*/ 
1117 bool pkgCacheListParser::NewProvidesAllArch(pkgCache::VerIterator 
&Ver
, string 
const &Package
, 
1118                                 string 
const &Version
, uint8_t const Flags
) { 
1119    pkgCache 
&Cache 
= Owner
->Cache
; 
1120    pkgCache::GrpIterator Grp 
= Cache
.FindGrp(Package
); 
1121    Dynamic
<pkgCache::GrpIterator
> DynGrp(Grp
); 
1123    if (Grp
.end() == true) 
1124       return NewProvides(Ver
, Package
, Cache
.NativeArch(), Version
, Flags
); 
1127       map_stringitem_t idxProvideVersion 
= 0; 
1128       if (Version
.empty() == false) { 
1129          idxProvideVersion 
= StoreString(pkgCacheGenerator::VERSIONNUMBER
, Version
); 
1130          if (unlikely(idxProvideVersion 
== 0)) 
1134       bool const isImplicit 
= (Flags 
& pkgCache::Flag::MultiArchImplicit
) == pkgCache::Flag::MultiArchImplicit
; 
1135       bool const isArchSpecific 
= (Flags 
& pkgCache::Flag::ArchSpecific
) == pkgCache::Flag::ArchSpecific
; 
1136       pkgCache::PkgIterator OwnerPkg 
= Ver
.ParentPkg(); 
1137       Dynamic
<pkgCache::PkgIterator
> DynOwnerPkg(OwnerPkg
); 
1138       pkgCache::PkgIterator Pkg
; 
1139       Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
); 
1140       for (Pkg 
= Grp
.PackageList(); Pkg
.end() == false; Pkg 
= Grp
.NextPkg(Pkg
)) 
1142          if (isImplicit 
&& OwnerPkg 
== Pkg
) 
1144          if (isArchSpecific 
== false && APT::Configuration::checkArchitecture(OwnerPkg
.Arch()) == false) 
1146          if (Owner
->NewProvides(Ver
, Pkg
, idxProvideVersion
, Flags
) == false) 
1153 bool pkgCacheListParser::SameVersion(unsigned short const Hash
,         /*{{{*/ 
1154       pkgCache::VerIterator 
const &Ver
) 
1156    return Hash 
== Ver
->Hash
; 
1159 // CacheGenerator::SelectReleaseFile - Select the current release file the indexes belong to    /*{{{*/ 
1160 bool pkgCacheGenerator::SelectReleaseFile(const string 
&File
,const string 
&Site
, 
1161                                    unsigned long Flags
) 
1163    if (File
.empty() && Site
.empty()) 
1165       CurrentRlsFile 
= NULL
; 
1169    // Get some space for the structure 
1170    map_pointer_t 
const idxFile 
= AllocateInMap(sizeof(*CurrentRlsFile
)); 
1171    if (unlikely(idxFile 
== 0)) 
1173    CurrentRlsFile 
= Cache
.RlsFileP 
+ idxFile
; 
1176    map_stringitem_t 
const idxFileName 
= WriteStringInMap(File
); 
1177    map_stringitem_t 
const idxSite 
= StoreString(MIXED
, Site
); 
1178    if (unlikely(idxFileName 
== 0 || idxSite 
== 0)) 
1180    CurrentRlsFile
->FileName 
= idxFileName
; 
1181    CurrentRlsFile
->Site 
= idxSite
; 
1182    CurrentRlsFile
->NextFile 
= Cache
.HeaderP
->RlsFileList
; 
1183    CurrentRlsFile
->Flags 
= Flags
; 
1184    CurrentRlsFile
->ID 
= Cache
.HeaderP
->ReleaseFileCount
; 
1186    Cache
.HeaderP
->RlsFileList 
= CurrentRlsFile 
- Cache
.RlsFileP
; 
1187    Cache
.HeaderP
->ReleaseFileCount
++; 
1192 // CacheGenerator::SelectFile - Select the current file being parsed    /*{{{*/ 
1193 // --------------------------------------------------------------------- 
1194 /* This is used to select which file is to be associated with all newly 
1195    added versions. The caller is responsible for setting the IMS fields. */ 
1196 bool pkgCacheGenerator::SelectFile(std::string 
const &File
, 
1197                                    pkgIndexFile 
const &Index
, 
1198                                    std::string 
const &Architecture
, 
1199                                    std::string 
const &Component
, 
1200                                    unsigned long const Flags
) 
1202    // Get some space for the structure 
1203    map_pointer_t 
const idxFile 
= AllocateInMap(sizeof(*CurrentFile
)); 
1204    if (unlikely(idxFile 
== 0)) 
1206    CurrentFile 
= Cache
.PkgFileP 
+ idxFile
; 
1209    map_stringitem_t 
const idxFileName 
= WriteStringInMap(File
); 
1210    if (unlikely(idxFileName 
== 0)) 
1212    CurrentFile
->FileName 
= idxFileName
; 
1213    CurrentFile
->NextFile 
= Cache
.HeaderP
->FileList
; 
1214    CurrentFile
->ID 
= Cache
.HeaderP
->PackageFileCount
; 
1215    map_stringitem_t 
const idxIndexType 
= StoreString(MIXED
, Index
.GetType()->Label
); 
1216    if (unlikely(idxIndexType 
== 0)) 
1218    CurrentFile
->IndexType 
= idxIndexType
; 
1219    if (Architecture
.empty()) 
1220       CurrentFile
->Architecture 
= 0; 
1223       map_stringitem_t 
const arch 
= StoreString(pkgCacheGenerator::MIXED
, Architecture
); 
1224       if (unlikely(arch 
== 0)) 
1226       CurrentFile
->Architecture 
= arch
; 
1228    map_stringitem_t 
const component 
= StoreString(pkgCacheGenerator::MIXED
, Component
); 
1229    if (unlikely(component 
== 0)) 
1231    CurrentFile
->Component 
= component
; 
1232    CurrentFile
->Flags 
= Flags
; 
1233    if (CurrentRlsFile 
!= NULL
) 
1234       CurrentFile
->Release 
= CurrentRlsFile 
- Cache
.RlsFileP
; 
1236       CurrentFile
->Release 
= 0; 
1238    Cache
.HeaderP
->FileList 
= CurrentFile 
- Cache
.PkgFileP
; 
1239    Cache
.HeaderP
->PackageFileCount
++; 
1242       Progress
->SubProgress(Index
.Size()); 
1246 // CacheGenerator::WriteUniqueString - Insert a unique string           /*{{{*/ 
1247 // --------------------------------------------------------------------- 
1248 /* This is used to create handles to strings. Given the same text it 
1249    always returns the same number */ 
1250 map_stringitem_t 
pkgCacheGenerator::StoreString(enum StringType 
const type
, const char *S
, 
1253    std::string 
const key(S
, Size
); 
1255    std::map
<std::string
,map_stringitem_t
> * strings
; 
1257       case MIXED
: strings 
= &strMixed
; break; 
1258       case PKGNAME
: strings 
= &strPkgNames
; break; 
1259       case VERSIONNUMBER
: strings 
= &strVersions
; break; 
1260       case SECTION
: strings 
= &strSections
; break; 
1261       default: _error
->Fatal("Unknown enum type used for string storage of '%s'", key
.c_str()); return 0; 
1264    std::map
<std::string
,map_stringitem_t
>::const_iterator 
const item 
= strings
->find(key
); 
1265    if (item 
!= strings
->end()) 
1266       return item
->second
; 
1268    map_stringitem_t 
const idxString 
= WriteStringInMap(S
,Size
); 
1269    strings
->insert(std::make_pair(key
, idxString
)); 
1273 // CheckValidity - Check that a cache is up-to-date                     /*{{{*/ 
1274 // --------------------------------------------------------------------- 
1275 /* This just verifies that each file in the list of index files exists, 
1276    has matching attributes with the cache and the cache does not have 
1278 class APT_HIDDEN ScopedErrorRevert 
{ 
1280    ScopedErrorRevert() { _error
->PushToStack(); } 
1281    ~ScopedErrorRevert() { _error
->RevertToStack(); } 
1283 static bool CheckValidity(const string 
&CacheFile
, 
1284                           pkgSourceList 
&List
, 
1285                           FileIterator 
const Start
, 
1286                           FileIterator 
const End
, 
1289    ScopedErrorRevert ser
; 
1290    bool const Debug 
= _config
->FindB("Debug::pkgCacheGen", false); 
1291    // No file, certainly invalid 
1292    if (CacheFile
.empty() == true || FileExists(CacheFile
) == false) 
1295          std::clog 
<< "CacheFile " << CacheFile 
<< " doesn't exist" << std::endl
; 
1299    if (List
.GetLastModifiedTime() > GetModificationTime(CacheFile
)) 
1302          std::clog 
<< "sources.list is newer than the cache" << std::endl
; 
1307    FileFd 
CacheF(CacheFile
,FileFd::ReadOnly
); 
1308    std::unique_ptr
<MMap
> Map(new MMap(CacheF
,0)); 
1309    pkgCache 
Cache(Map
.get()); 
1310    if (_error
->PendingError() || Map
->Size() == 0) 
1313          std::clog 
<< "Errors are pending or Map is empty() for " << CacheFile 
<< std::endl
; 
1317    std::unique_ptr
<bool[]> RlsVisited(new bool[Cache
.HeaderP
->ReleaseFileCount
]); 
1318    memset(RlsVisited
.get(),0,sizeof(RlsVisited
[0])*Cache
.HeaderP
->ReleaseFileCount
); 
1319    std::vector
<pkgIndexFile 
*> Files
; 
1320    for (pkgSourceList::const_iterator i 
= List
.begin(); i 
!= List
.end(); ++i
) 
1323          std::clog 
<< "Checking RlsFile " << (*i
)->Describe() << ": "; 
1324       pkgCache::RlsFileIterator 
const RlsFile 
= (*i
)->FindInCache(Cache
, true); 
1325       if (RlsFile
.end() == true) 
1328             std::clog 
<< "FindInCache returned end-Pointer" << std::endl
; 
1332       RlsVisited
[RlsFile
->ID
] = true; 
1334          std::clog 
<< "with ID " << RlsFile
->ID 
<< " is valid" << std::endl
; 
1336       std::vector 
<pkgIndexFile 
*> const * const Indexes 
= (*i
)->GetIndexFiles(); 
1337       std::copy_if(Indexes
->begin(), Indexes
->end(), std::back_inserter(Files
), 
1338             [](pkgIndexFile 
const * const I
) { return I
->HasPackages(); }); 
1340    for (unsigned I 
= 0; I 
!= Cache
.HeaderP
->ReleaseFileCount
; ++I
) 
1341       if (RlsVisited
[I
] == false) 
1344             std::clog 
<< "RlsFile with ID" << I 
<< " wasn't visited" << std::endl
; 
1348    std::copy(Start
, End
, std::back_inserter(Files
)); 
1350    /* Now we check every index file, see if it is in the cache, 
1351       verify the IMS data and check that it is on the disk too.. */ 
1352    std::unique_ptr
<bool[]> Visited(new bool[Cache
.HeaderP
->PackageFileCount
]); 
1353    memset(Visited
.get(),0,sizeof(Visited
[0])*Cache
.HeaderP
->PackageFileCount
); 
1354    for (std::vector
<pkgIndexFile 
*>::const_reverse_iterator PkgFile 
= Files
.rbegin(); PkgFile 
!= Files
.rend(); ++PkgFile
) 
1357          std::clog 
<< "Checking PkgFile " << (*PkgFile
)->Describe() << ": "; 
1358       if ((*PkgFile
)->Exists() == false) 
1361             std::clog 
<< "file doesn't exist" << std::endl
; 
1365       // FindInCache is also expected to do an IMS check. 
1366       pkgCache::PkgFileIterator File 
= (*PkgFile
)->FindInCache(Cache
); 
1367       if (File
.end() == true) 
1370             std::clog 
<< "FindInCache returned end-Pointer" << std::endl
; 
1374       Visited
[File
->ID
] = true; 
1376          std::clog 
<< "with ID " << File
->ID 
<< " is valid" << std::endl
; 
1379    for (unsigned I 
= 0; I 
!= Cache
.HeaderP
->PackageFileCount
; I
++) 
1380       if (Visited
[I
] == false) 
1383             std::clog 
<< "PkgFile with ID" << I 
<< " wasn't visited" << std::endl
; 
1387    if (_error
->PendingError() == true) 
1391          std::clog 
<< "Validity failed because of pending errors:" << std::endl
; 
1392          _error
->DumpErrors(std::clog
, GlobalError::DEBUG
, false); 
1398       *OutMap 
= Map
.release(); 
1402 // ComputeSize - Compute the total size of a bunch of files             /*{{{*/ 
1403 // --------------------------------------------------------------------- 
1404 /* Size is kind of an abstract notion that is only used for the progress 
1406 static map_filesize_t 
ComputeSize(pkgSourceList 
const * const List
, FileIterator Start
,FileIterator End
) 
1408    map_filesize_t TotalSize 
= 0; 
1411       for (pkgSourceList::const_iterator i 
= List
->begin(); i 
!= List
->end(); ++i
) 
1413          std::vector 
<pkgIndexFile 
*> *Indexes 
= (*i
)->GetIndexFiles(); 
1414          for (std::vector
<pkgIndexFile 
*>::const_iterator j 
= Indexes
->begin(); j 
!= Indexes
->end(); ++j
) 
1415             if ((*j
)->HasPackages() == true) 
1416                TotalSize 
+= (*j
)->Size(); 
1420    for (; Start 
< End
; ++Start
) 
1422       if ((*Start
)->HasPackages() == false) 
1424       TotalSize 
+= (*Start
)->Size(); 
1429 // BuildCache - Merge the list of index files into the cache            /*{{{*/ 
1430 static bool BuildCache(pkgCacheGenerator 
&Gen
, 
1431                        OpProgress 
* const Progress
, 
1432                        map_filesize_t 
&CurrentSize
,map_filesize_t TotalSize
, 
1433                        pkgSourceList 
const * const List
, 
1434                        FileIterator 
const Start
, FileIterator 
const End
) 
1436    std::vector
<pkgIndexFile 
*> Files
; 
1437    bool mergeFailure 
= false; 
1439    auto const indexFileMerge 
= [&](pkgIndexFile 
* const I
) { 
1440       if (I
->HasPackages() == false || mergeFailure
) 
1443       if (I
->Exists() == false) 
1446       if (I
->FindInCache(Gen
.GetCache()).end() == false) 
1448          _error
->Warning("Duplicate sources.list entry %s", 
1449                I
->Describe().c_str()); 
1453       map_filesize_t 
const Size 
= I
->Size(); 
1454       if (Progress 
!= NULL
) 
1455          Progress
->OverallProgress(CurrentSize
, TotalSize
, Size
, _("Reading package lists")); 
1456       CurrentSize 
+= Size
; 
1458       if (I
->Merge(Gen
,Progress
) == false) 
1459          mergeFailure 
= true; 
1464       for (pkgSourceList::const_iterator i 
= List
->begin(); i 
!= List
->end(); ++i
) 
1466          if ((*i
)->FindInCache(Gen
.GetCache(), false).end() == false) 
1468             _error
->Warning("Duplicate sources.list entry %s", 
1469                   (*i
)->Describe().c_str()); 
1473          if ((*i
)->Merge(Gen
, Progress
) == false) 
1476          std::vector 
<pkgIndexFile 
*> *Indexes 
= (*i
)->GetIndexFiles(); 
1477          if (Indexes 
!= NULL
) 
1478             std::for_each(Indexes
->begin(), Indexes
->end(), indexFileMerge
); 
1486       Gen
.SelectReleaseFile("", ""); 
1487       std::for_each(Start
, End
, indexFileMerge
); 
1494 // CacheGenerator::MakeStatusCache - Construct the status cache         /*{{{*/ 
1495 // --------------------------------------------------------------------- 
1496 /* This makes sure that the status cache (the cache that has all  
1497    index files from the sources list and all local ones) is ready 
1498    to be mmaped. If OutMap is not zero then a MMap object representing 
1499    the cache will be stored there. This is pretty much mandetory if you 
1500    are using AllowMem. AllowMem lets the function be run as non-root 
1501    where it builds the cache 'fast' into a memory buffer. */ 
1502 static DynamicMMap
* CreateDynamicMMap(FileFd 
* const CacheF
, unsigned long Flags
) 
1504    map_filesize_t 
const MapStart 
= _config
->FindI("APT::Cache-Start", 24*1024*1024); 
1505    map_filesize_t 
const MapGrow 
= _config
->FindI("APT::Cache-Grow", 1*1024*1024); 
1506    map_filesize_t 
const MapLimit 
= _config
->FindI("APT::Cache-Limit", 0); 
1507    Flags 
|= MMap::Moveable
; 
1508    if (_config
->FindB("APT::Cache-Fallback", false) == true) 
1509       Flags 
|= MMap::Fallback
; 
1511       return new DynamicMMap(*CacheF
, Flags
, MapStart
, MapGrow
, MapLimit
); 
1513       return new DynamicMMap(Flags
, MapStart
, MapGrow
, MapLimit
); 
1515 static bool writeBackMMapToFile(pkgCacheGenerator 
* const Gen
, DynamicMMap 
* const Map
, 
1516       std::string 
const &FileName
) 
1518    FileFd 
SCacheF(FileName
, FileFd::WriteAtomic
); 
1519    if (SCacheF
.IsOpen() == false || SCacheF
.Failed()) 
1522    fchmod(SCacheF
.Fd(),0644); 
1524    // Write out the main data 
1525    if (SCacheF
.Write(Map
->Data(),Map
->Size()) == false) 
1526       return _error
->Error(_("IO Error saving source cache")); 
1529    // Write out the proper header 
1530    Gen
->GetCache().HeaderP
->Dirty 
= false; 
1531    if (SCacheF
.Seek(0) == false || 
1532          SCacheF
.Write(Map
->Data(),sizeof(*Gen
->GetCache().HeaderP
)) == false) 
1533       return _error
->Error(_("IO Error saving source cache")); 
1534    Gen
->GetCache().HeaderP
->Dirty 
= true; 
1538 static bool loadBackMMapFromFile(std::unique_ptr
<pkgCacheGenerator
> &Gen
, 
1539       std::unique_ptr
<DynamicMMap
> &Map
, OpProgress 
* const Progress
, std::string 
const &FileName
) 
1541    Map
.reset(CreateDynamicMMap(NULL
, 0)); 
1542    FileFd 
CacheF(FileName
, FileFd::ReadOnly
); 
1543    if (CacheF
.IsOpen() == false || CacheF
.Failed()) 
1545    _error
->PushToStack(); 
1546    map_pointer_t 
const alloc 
= Map
->RawAllocate(CacheF
.Size()); 
1547    bool const newError 
= _error
->PendingError(); 
1548    _error
->MergeWithStack(); 
1549    if (alloc 
== 0 && newError
) 
1551    if (CacheF
.Read((unsigned char *)Map
->Data() + alloc
, CacheF
.Size()) == false) 
1553    Gen
.reset(new pkgCacheGenerator(Map
.get(),Progress
)); 
1556 APT_DEPRECATED 
bool pkgMakeStatusCache(pkgSourceList 
&List
,OpProgress 
&Progress
, 
1557                         MMap 
**OutMap
, bool AllowMem
) 
1558    { return pkgCacheGenerator::MakeStatusCache(List
, &Progress
, OutMap
, AllowMem
); } 
1559 bool pkgCacheGenerator::MakeStatusCache(pkgSourceList 
&List
,OpProgress 
*Progress
, 
1562    // FIXME: deprecate the ignored AllowMem parameter 
1563    bool const Debug 
= _config
->FindB("Debug::pkgCacheGen", false); 
1565    std::vector
<pkgIndexFile 
*> Files
; 
1566    if (_system
->AddStatusFiles(Files
) == false) 
1569    // Decide if we can write to the files.. 
1570    string 
const CacheFile 
= _config
->FindFile("Dir::Cache::pkgcache"); 
1571    string 
const SrcCacheFile 
= _config
->FindFile("Dir::Cache::srcpkgcache"); 
1573    // ensure the cache directory exists 
1574    if (CacheFile
.empty() == false || SrcCacheFile
.empty() == false) 
1576       string dir 
= _config
->FindDir("Dir::Cache"); 
1577       size_t const len 
= dir
.size(); 
1578       if (len 
> 5 && dir
.find("/apt/", len 
- 6, 5) == len 
- 5) 
1579          dir 
= dir
.substr(0, len 
- 5); 
1580       if (CacheFile
.empty() == false) 
1581          CreateDirectory(dir
, flNotFile(CacheFile
)); 
1582       if (SrcCacheFile
.empty() == false) 
1583          CreateDirectory(dir
, flNotFile(SrcCacheFile
)); 
1586    if (Progress 
!= NULL
) 
1587       Progress
->OverallProgress(0,1,1,_("Reading package lists")); 
1589    bool pkgcache_fine 
= false; 
1590    bool srcpkgcache_fine 
= false; 
1591    bool volatile_fine 
= List
.GetVolatileFiles().empty(); 
1593    if (CheckValidity(CacheFile
, List
, Files
.begin(), Files
.end(), volatile_fine 
? OutMap 
: NULL
) == true) 
1596          std::clog 
<< "pkgcache.bin is valid - no need to build any cache" << std::endl
; 
1597       pkgcache_fine 
= true; 
1598       srcpkgcache_fine 
= true; 
1600    if (pkgcache_fine 
== false) 
1602       if (CheckValidity(SrcCacheFile
, List
, Files
.end(), Files
.end()) == true) 
1605             std::clog 
<< "srcpkgcache.bin is valid - it can be reused" << std::endl
; 
1606          srcpkgcache_fine 
= true; 
1610    if (volatile_fine 
== true && srcpkgcache_fine 
== true && pkgcache_fine 
== true) 
1612       if (Progress 
!= NULL
) 
1613          Progress
->OverallProgress(1,1,1,_("Reading package lists")); 
1617    bool Writeable 
= false; 
1618    if (srcpkgcache_fine 
== false || pkgcache_fine 
== false) 
1620       if (CacheFile
.empty() == false) 
1621          Writeable 
= access(flNotFile(CacheFile
).c_str(),W_OK
) == 0; 
1622       else if (SrcCacheFile
.empty() == false) 
1623          Writeable 
= access(flNotFile(SrcCacheFile
).c_str(),W_OK
) == 0; 
1626          std::clog 
<< "Do we have write-access to the cache files? " << (Writeable 
? "YES" : "NO") << std::endl
; 
1629    // At this point we know we need to construct something, so get storage ready 
1630    std::unique_ptr
<DynamicMMap
> Map(CreateDynamicMMap(NULL
, 0)); 
1632       std::clog 
<< "Open memory Map (not filebased)" << std::endl
; 
1634    std::unique_ptr
<pkgCacheGenerator
> Gen
{nullptr}; 
1635    map_filesize_t CurrentSize 
= 0; 
1636    std::vector
<pkgIndexFile
*> VolatileFiles 
= List
.GetVolatileFiles(); 
1637    map_filesize_t TotalSize 
= ComputeSize(NULL
, VolatileFiles
.begin(), VolatileFiles
.end()); 
1638    if (srcpkgcache_fine 
== true && pkgcache_fine 
== false) 
1641          std::clog 
<< "srcpkgcache.bin was valid - populate MMap with it" << std::endl
; 
1642       if (loadBackMMapFromFile(Gen
, Map
, Progress
, SrcCacheFile
) == false) 
1644       srcpkgcache_fine 
= true; 
1645       TotalSize 
+= ComputeSize(NULL
, Files
.begin(), Files
.end()); 
1647    else if (srcpkgcache_fine 
== false) 
1650          std::clog 
<< "srcpkgcache.bin is NOT valid - rebuild" << std::endl
; 
1651       Gen
.reset(new pkgCacheGenerator(Map
.get(),Progress
)); 
1653       TotalSize 
+= ComputeSize(&List
, Files
.begin(),Files
.end()); 
1654       if (BuildCache(*Gen
, Progress
, CurrentSize
, TotalSize
, &List
, 
1655                Files
.end(),Files
.end()) == false) 
1658       if (Writeable 
== true && SrcCacheFile
.empty() == false) 
1659          if (writeBackMMapToFile(Gen
.get(), Map
.get(), SrcCacheFile
) == false) 
1663    if (pkgcache_fine 
== false) 
1666          std::clog 
<< "Building status cache in pkgcache.bin now" << std::endl
; 
1667       if (BuildCache(*Gen
, Progress
, CurrentSize
, TotalSize
, NULL
, 
1668                Files
.begin(), Files
.end()) == false) 
1671       if (Writeable 
== true && CacheFile
.empty() == false) 
1672          if (writeBackMMapToFile(Gen
.get(), Map
.get(), CacheFile
) == false) 
1677       std::clog 
<< "Caches done. Now bring in the volatile files (if any)" << std::endl
; 
1679    if (volatile_fine 
== false) 
1684             std::clog 
<< "Populate new MMap with cachefile contents" << std::endl
; 
1685          if (loadBackMMapFromFile(Gen
, Map
, Progress
, CacheFile
) == false) 
1689       Files 
= List
.GetVolatileFiles(); 
1690       if (BuildCache(*Gen
, Progress
, CurrentSize
, TotalSize
, NULL
, 
1691                Files
.begin(), Files
.end()) == false) 
1695    if (OutMap 
!= nullptr) 
1696       *OutMap 
= Map
.release(); 
1699       std::clog 
<< "Everything is ready for shipping" << std::endl
; 
1703 // CacheGenerator::MakeOnlyStatusCache - Build only a status files cache/*{{{*/ 
1704 class APT_HIDDEN ScopedErrorMerge 
{ 
1706    ScopedErrorMerge() { _error
->PushToStack(); } 
1707    ~ScopedErrorMerge() { _error
->MergeWithStack(); } 
1709 APT_DEPRECATED 
bool pkgMakeOnlyStatusCache(OpProgress 
&Progress
,DynamicMMap 
**OutMap
) 
1710    { return pkgCacheGenerator::MakeOnlyStatusCache(&Progress
, OutMap
); } 
1711 bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress 
*Progress
,DynamicMMap 
**OutMap
) 
1713    std::vector
<pkgIndexFile 
*> Files
; 
1714    if (_system
->AddStatusFiles(Files
) == false) 
1717    ScopedErrorMerge sem
; 
1718    std::unique_ptr
<DynamicMMap
> Map(CreateDynamicMMap(NULL
, 0)); 
1719    map_filesize_t CurrentSize 
= 0; 
1720    map_filesize_t TotalSize 
= 0; 
1721    TotalSize 
= ComputeSize(NULL
, Files
.begin(), Files
.end()); 
1723    // Build the status cache 
1724    if (Progress 
!= NULL
) 
1725       Progress
->OverallProgress(0,1,1,_("Reading package lists")); 
1726    pkgCacheGenerator 
Gen(Map
.get(),Progress
); 
1727    if (_error
->PendingError() == true) 
1729    if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
, NULL
, 
1730                   Files
.begin(), Files
.end()) == false) 
1733    if (_error
->PendingError() == true) 
1735    *OutMap 
= Map
.release(); 
1740 // IsDuplicateDescription                                               /*{{{*/ 
1741 static bool IsDuplicateDescription(pkgCache::DescIterator Desc
, 
1742                             MD5SumValue 
const &CurMd5
, std::string 
const &CurLang
) 
1744    // Descriptions in the same link-list have all the same md5 
1745    if (Desc
.end() == true || MD5SumValue(Desc
.md5()) != CurMd5
) 
1747    for (; Desc
.end() == false; ++Desc
) 
1748       if (Desc
.LanguageCode() == CurLang
) 
1754 pkgCacheListParser::pkgCacheListParser() : Owner(NULL
), OldDepLast(NULL
), d(NULL
) {} 
1755 pkgCacheListParser::~pkgCacheListParser() {}