]>
git.saurik.com Git - apt.git/blob - apt-pkg/pkgcachegen.cc
f70cbd02a67e62b8b4e325c0029d0b3b908dca9c
   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/aptconfiguration.h> 
  22 #include <apt-pkg/strutl.h> 
  23 #include <apt-pkg/sptr.h> 
  24 #include <apt-pkg/pkgsystem.h> 
  25 #include <apt-pkg/macros.h> 
  26 #include <apt-pkg/tagfile.h> 
  27 #include <apt-pkg/metaindex.h> 
  28 #include <apt-pkg/fileutl.h> 
  38 typedef std::vector
<pkgIndexFile 
*>::iterator FileIterator
; 
  39 template <typename Iter
> std::vector
<Iter
*> pkgCacheGenerator::Dynamic
<Iter
>::toReMap
; 
  41 static bool IsDuplicateDescription(pkgCache::DescIterator Desc
, 
  42                             MD5SumValue 
const &CurMd5
, std::string 
const &CurLang
); 
  46 // CacheGenerator::pkgCacheGenerator - Constructor                      /*{{{*/ 
  47 // --------------------------------------------------------------------- 
  48 /* We set the dirty flag and make sure that is written to the disk */ 
  49 pkgCacheGenerator::pkgCacheGenerator(DynamicMMap 
*pMap
,OpProgress 
*Prog
) : 
  50                     Map(*pMap
), Cache(pMap
,false), Progress(Prog
), 
  54    memset(UniqHash
,0,sizeof(UniqHash
)); 
  56    if (_error
->PendingError() == true) 
  61       // Setup the map interface.. 
  62       Cache
.HeaderP 
= (pkgCache::Header 
*)Map
.Data(); 
  63       if (Map
.RawAllocate(sizeof(pkgCache::Header
)) == 0 && _error
->PendingError() == true) 
  66       Map
.UsePools(*Cache
.HeaderP
->Pools
,sizeof(Cache
.HeaderP
->Pools
)/sizeof(Cache
.HeaderP
->Pools
[0])); 
  69       *Cache
.HeaderP 
= pkgCache::Header(); 
  70       map_ptrloc 
const idxVerSysName 
= WriteStringInMap(_system
->VS
->Label
); 
  71       Cache
.HeaderP
->VerSysName 
= idxVerSysName
; 
  72       map_ptrloc 
const idxArchitecture 
= WriteStringInMap(_config
->Find("APT::Architecture")); 
  73       Cache
.HeaderP
->Architecture 
= idxArchitecture
; 
  74       if (unlikely(idxVerSysName 
== 0 || idxArchitecture 
== 0)) 
  80       // Map directly from the existing file 
  82       Map
.UsePools(*Cache
.HeaderP
->Pools
,sizeof(Cache
.HeaderP
->Pools
)/sizeof(Cache
.HeaderP
->Pools
[0])); 
  83       if (Cache
.VS 
!= _system
->VS
) 
  85          _error
->Error(_("Cache has an incompatible versioning system")); 
  90    Cache
.HeaderP
->Dirty 
= true; 
  91    Map
.Sync(0,sizeof(pkgCache::Header
)); 
  94 // CacheGenerator::~pkgCacheGenerator - Destructor                      /*{{{*/ 
  95 // --------------------------------------------------------------------- 
  96 /* We sync the data then unset the dirty flag in two steps so as to 
  97    advoid a problem during a crash */ 
  98 pkgCacheGenerator::~pkgCacheGenerator() 
 100    if (_error
->PendingError() == true) 
 102    if (Map
.Sync() == false) 
 105    Cache
.HeaderP
->Dirty 
= false; 
 106    Cache
.HeaderP
->CacheFileSize 
= Map
.Size(); 
 107    Map
.Sync(0,sizeof(pkgCache::Header
)); 
 110 void pkgCacheGenerator::ReMap(void const * const oldMap
, void const * const newMap
) {/*{{{*/ 
 111    if (oldMap 
== newMap
) 
 114    if (_config
->FindB("Debug::pkgCacheGen", false)) 
 115       std::clog 
<< "Remaping from " << oldMap 
<< " to " << newMap 
<< std::endl
; 
 119    CurrentFile 
+= (pkgCache::PackageFile
*) newMap 
- (pkgCache::PackageFile
*) oldMap
; 
 121    for (size_t i 
= 0; i 
< _count(UniqHash
); ++i
) 
 122       if (UniqHash
[i
] != 0) 
 123          UniqHash
[i
] += (pkgCache::StringItem
*) newMap 
- (pkgCache::StringItem
*) oldMap
; 
 125    for (std::vector
<pkgCache::GrpIterator
*>::const_iterator i 
= Dynamic
<pkgCache::GrpIterator
>::toReMap
.begin(); 
 126         i 
!= Dynamic
<pkgCache::GrpIterator
>::toReMap
.end(); ++i
) 
 127       (*i
)->ReMap(oldMap
, newMap
); 
 128    for (std::vector
<pkgCache::PkgIterator
*>::const_iterator i 
= Dynamic
<pkgCache::PkgIterator
>::toReMap
.begin(); 
 129         i 
!= Dynamic
<pkgCache::PkgIterator
>::toReMap
.end(); ++i
) 
 130       (*i
)->ReMap(oldMap
, newMap
); 
 131    for (std::vector
<pkgCache::VerIterator
*>::const_iterator i 
= Dynamic
<pkgCache::VerIterator
>::toReMap
.begin(); 
 132         i 
!= Dynamic
<pkgCache::VerIterator
>::toReMap
.end(); ++i
) 
 133       (*i
)->ReMap(oldMap
, newMap
); 
 134    for (std::vector
<pkgCache::DepIterator
*>::const_iterator i 
= Dynamic
<pkgCache::DepIterator
>::toReMap
.begin(); 
 135         i 
!= Dynamic
<pkgCache::DepIterator
>::toReMap
.end(); ++i
) 
 136       (*i
)->ReMap(oldMap
, newMap
); 
 137    for (std::vector
<pkgCache::DescIterator
*>::const_iterator i 
= Dynamic
<pkgCache::DescIterator
>::toReMap
.begin(); 
 138         i 
!= Dynamic
<pkgCache::DescIterator
>::toReMap
.end(); ++i
) 
 139       (*i
)->ReMap(oldMap
, newMap
); 
 140    for (std::vector
<pkgCache::PrvIterator
*>::const_iterator i 
= Dynamic
<pkgCache::PrvIterator
>::toReMap
.begin(); 
 141         i 
!= Dynamic
<pkgCache::PrvIterator
>::toReMap
.end(); ++i
) 
 142       (*i
)->ReMap(oldMap
, newMap
); 
 143    for (std::vector
<pkgCache::PkgFileIterator
*>::const_iterator i 
= Dynamic
<pkgCache::PkgFileIterator
>::toReMap
.begin(); 
 144         i 
!= Dynamic
<pkgCache::PkgFileIterator
>::toReMap
.end(); ++i
) 
 145       (*i
)->ReMap(oldMap
, newMap
); 
 147 // CacheGenerator::WriteStringInMap                                     /*{{{*/ 
 148 map_ptrloc 
pkgCacheGenerator::WriteStringInMap(const char *String
, 
 149                                         const unsigned long &Len
) { 
 150    void const * const oldMap 
= Map
.Data(); 
 151    map_ptrloc 
const index 
= Map
.WriteString(String
, Len
); 
 153       ReMap(oldMap
, Map
.Data()); 
 157 // CacheGenerator::WriteStringInMap                                     /*{{{*/ 
 158 map_ptrloc 
pkgCacheGenerator::WriteStringInMap(const char *String
) { 
 159    void const * const oldMap 
= Map
.Data(); 
 160    map_ptrloc 
const index 
= Map
.WriteString(String
); 
 162       ReMap(oldMap
, Map
.Data()); 
 166 map_ptrloc 
pkgCacheGenerator::AllocateInMap(const unsigned long &size
) {/*{{{*/ 
 167    void const * const oldMap 
= Map
.Data(); 
 168    map_ptrloc 
const index 
= Map
.Allocate(size
); 
 170       ReMap(oldMap
, Map
.Data()); 
 174 // CacheGenerator::MergeList - Merge the package list                   /*{{{*/ 
 175 // --------------------------------------------------------------------- 
 176 /* This provides the generation of the entries in the cache. Each loop 
 177    goes through a single package record from the underlying parse engine. */ 
 178 bool pkgCacheGenerator::MergeList(ListParser 
&List
, 
 179                                   pkgCache::VerIterator 
*OutVer
) 
 183    unsigned int Counter 
= 0; 
 184    while (List
.Step() == true) 
 186       string 
const PackageName 
= List
.Package(); 
 187       if (PackageName
.empty() == true) 
 191       if (Counter 
% 100 == 0 && Progress 
!= 0) 
 192          Progress
->Progress(List
.Offset()); 
 194       string Arch 
= List
.Architecture(); 
 195       string 
const Version 
= List
.Version(); 
 196       if (Version
.empty() == true && Arch
.empty() == true) 
 198          if (MergeListGroup(List
, PackageName
) == false) 
 202       if (Arch
.empty() == true) 
 203          Arch 
= _config
->Find("APT::Architecture"); 
 205       // Get a pointer to the package structure 
 206       pkgCache::PkgIterator Pkg
; 
 207       Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
); 
 208       if (NewPackage(Pkg
, PackageName
, Arch
) == false) 
 209          // TRANSLATOR: The first placeholder is a package name, 
 210          // the other two should be copied verbatim as they include debug info 
 211          return _error
->Error(_("Error occurred while processing %s (%s%d)"), 
 212                               PackageName
.c_str(), "NewPackage", 1); 
 215       if (Version
.empty() == true) 
 217          if (MergeListPackage(List
, Pkg
) == false) 
 222          if (MergeListVersion(List
, Pkg
, Version
, OutVer
) == false) 
 228          FoundFileDeps 
|= List
.HasFileDeps(); 
 233    if (Cache
.HeaderP
->PackageCount 
>= (1ULL<<sizeof(Cache
.PkgP
->ID
)*8)-1) 
 234       return _error
->Error(_("Wow, you exceeded the number of package " 
 235                              "names this APT is capable of.")); 
 236    if (Cache
.HeaderP
->VersionCount 
>= (1ULL<<(sizeof(Cache
.VerP
->ID
)*8))-1) 
 237       return _error
->Error(_("Wow, you exceeded the number of versions " 
 238                              "this APT is capable of.")); 
 239    if (Cache
.HeaderP
->DescriptionCount 
>= (1ULL<<(sizeof(Cache
.DescP
->ID
)*8))-1) 
 240       return _error
->Error(_("Wow, you exceeded the number of descriptions " 
 241                              "this APT is capable of.")); 
 242    if (Cache
.HeaderP
->DependsCount 
>= (1ULL<<(sizeof(Cache
.DepP
->ID
)*8))-1ULL) 
 243       return _error
->Error(_("Wow, you exceeded the number of dependencies " 
 244                              "this APT is capable of.")); 
 246    FoundFileDeps 
|= List
.HasFileDeps(); 
 249 // CacheGenerator::MergeListGroup                                       /*{{{*/ 
 250 bool pkgCacheGenerator::MergeListGroup(ListParser 
&List
, std::string 
const &GrpName
) 
 252    pkgCache::GrpIterator Grp 
= Cache
.FindGrp(GrpName
); 
 253    // a group has no data on it's own, only packages have it but these 
 254    // stanzas like this come from Translation- files to add descriptions, 
 255    // but without a version we don't need a description for it… 
 256    if (Grp
.end() == true) 
 258    Dynamic
<pkgCache::GrpIterator
> DynGrp(Grp
); 
 260    pkgCache::PkgIterator Pkg
; 
 261    Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
); 
 262    for (Pkg 
= Grp
.PackageList(); Pkg
.end() == false; Pkg 
= Grp
.NextPkg(Pkg
)) 
 263       if (MergeListPackage(List
, Pkg
) == false) 
 269 // CacheGenerator::MergeListPackage                                     /*{{{*/ 
 270 bool pkgCacheGenerator::MergeListPackage(ListParser 
&List
, pkgCache::PkgIterator 
&Pkg
) 
 272    // we first process the package, then the descriptions 
 273    // (for deb this package processing is in fact a no-op) 
 274    pkgCache::VerIterator 
Ver(Cache
); 
 275    Dynamic
<pkgCache::VerIterator
> DynVer(Ver
); 
 276    if (List
.UsePackage(Pkg
, Ver
) == false) 
 277       return _error
->Error(_("Error occurred while processing %s (%s%d)"), 
 278                            Pkg
.Name(), "UsePackage", 1); 
 280    // Find the right version to write the description 
 281    MD5SumValue CurMd5 
= List
.Description_md5(); 
 282    std::string CurLang 
= List
.DescriptionLanguage(); 
 284    for (Ver 
= Pkg
.VersionList(); Ver
.end() == false; ++Ver
) 
 286       pkgCache::DescIterator Desc 
= Ver
.DescriptionList(); 
 288       // a version can only have one md5 describing it 
 289       if (Desc
.end() == true || MD5SumValue(Desc
.md5()) != CurMd5
) 
 292       // don't add a new description if we have one for the given 
 294       if (IsDuplicateDescription(Desc
, CurMd5
, CurLang
) == true) 
 297       Dynamic
<pkgCache::DescIterator
> DynDesc(Desc
); 
 298       // we add at the end, so that the start is constant as we need 
 299       // that to be able to efficiently share these lists 
 300       map_ptrloc 
*LastDesc 
= &Ver
->DescriptionList
; 
 301       for (;Desc
.end() == false && Desc
->NextDesc 
!= 0; ++Desc
); 
 302       if (Desc
.end() == false) 
 303          LastDesc 
= &Desc
->NextDesc
; 
 305       void const * const oldMap 
= Map
.Data(); 
 306       map_ptrloc 
const descindex 
= NewDescription(Desc
, CurLang
, CurMd5
, *LastDesc
); 
 307       if (unlikely(descindex 
== 0 && _error
->PendingError())) 
 308          return _error
->Error(_("Error occurred while processing %s (%s%d)"), 
 309                               Pkg
.Name(), "NewDescription", 1); 
 310       if (oldMap 
!= Map
.Data()) 
 311          LastDesc 
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
; 
 312       *LastDesc 
= descindex
; 
 313       Desc
->ParentPkg 
= Pkg
.Index(); 
 315       if ((*LastDesc 
== 0 && _error
->PendingError()) || NewFileDesc(Desc
,List
) == false) 
 316          return _error
->Error(_("Error occurred while processing %s (%s%d)"), 
 317                               Pkg
.Name(), "NewFileDesc", 1); 
 319       // we can stop here as all "same" versions will share the description 
 326 // CacheGenerator::MergeListVersion                                     /*{{{*/ 
 327 bool pkgCacheGenerator::MergeListVersion(ListParser 
&List
, pkgCache::PkgIterator 
&Pkg
, 
 328                                          std::string 
const &Version
, pkgCache::VerIterator
* &OutVer
) 
 330    pkgCache::VerIterator Ver 
= Pkg
.VersionList(); 
 331    Dynamic
<pkgCache::VerIterator
> DynVer(Ver
); 
 332    map_ptrloc 
*LastVer 
= &Pkg
->VersionList
; 
 333    void const * oldMap 
= Map
.Data(); 
 335    unsigned long const Hash 
= List
.VersionHash(); 
 336    if (Ver
.end() == false) 
 338       /* We know the list is sorted so we use that fact in the search. 
 339          Insertion of new versions is done with correct sorting */ 
 341       for (; Ver
.end() == false; LastVer 
= &Ver
->NextVer
, Ver
++) 
 343          Res 
= Cache
.VS
->CmpVersion(Version
,Ver
.VerStr()); 
 344          // Version is higher as current version - insert here 
 347          // Versionstrings are equal - is hash also equal? 
 348          if (Res 
== 0 && Ver
->Hash 
== Hash
) 
 350          // proceed with the next till we have either the right 
 351          // or we found another version (which will be lower) 
 354       /* We already have a version for this item, record that we saw it */ 
 355       if (Res 
== 0 && Ver
.end() == false && Ver
->Hash 
== Hash
) 
 357          if (List
.UsePackage(Pkg
,Ver
) == false) 
 358             return _error
->Error(_("Error occurred while processing %s (%s%d)"), 
 359                                  Pkg
.Name(), "UsePackage", 2); 
 361          if (NewFileVer(Ver
,List
) == false) 
 362             return _error
->Error(_("Error occurred while processing %s (%s%d)"), 
 363                                  Pkg
.Name(), "NewFileVer", 1); 
 365          // Read only a single record and return 
 377    map_ptrloc 
const verindex 
= NewVersion(Ver
,Version
,*LastVer
); 
 378    if (verindex 
== 0 && _error
->PendingError()) 
 379       return _error
->Error(_("Error occurred while processing %s (%s%d)"), 
 380                            Pkg
.Name(), "NewVersion", 1); 
 382    if (oldMap 
!= Map
.Data()) 
 383          LastVer 
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
; 
 385    Ver
->ParentPkg 
= Pkg
.Index(); 
 388    if (unlikely(List
.NewVersion(Ver
) == false)) 
 389       return _error
->Error(_("Error occurred while processing %s (%s%d)"), 
 390                            Pkg
.Name(), "NewVersion", 2); 
 392    if (unlikely(List
.UsePackage(Pkg
,Ver
) == false)) 
 393       return _error
->Error(_("Error occurred while processing %s (%s%d)"), 
 394                            Pkg
.Name(), "UsePackage", 3); 
 396    if (unlikely(NewFileVer(Ver
,List
) == false)) 
 397       return _error
->Error(_("Error occurred while processing %s (%s%d)"), 
 398                            Pkg
.Name(), "NewFileVer", 2); 
 400    pkgCache::GrpIterator Grp 
= Pkg
.Group(); 
 401    Dynamic
<pkgCache::GrpIterator
> DynGrp(Grp
); 
 403    /* If it is the first version of this package we need to add implicit 
 404       Multi-Arch dependencies to all other package versions in the group now - 
 405       otherwise we just add them for this new version */ 
 406    if (Pkg
.VersionList()->NextVer 
== 0) 
 408       pkgCache::PkgIterator P 
= Grp
.PackageList(); 
 409       Dynamic
<pkgCache::PkgIterator
> DynP(P
); 
 410       for (; P
.end() != true; P 
= Grp
.NextPkg(P
)) 
 412          if (P
->ID 
== Pkg
->ID
) 
 414          pkgCache::VerIterator V 
= P
.VersionList(); 
 415          Dynamic
<pkgCache::VerIterator
> DynV(V
); 
 416          for (; V
.end() != true; ++V
) 
 417             if (unlikely(AddImplicitDepends(V
, Pkg
) == false)) 
 418                return _error
->Error(_("Error occurred while processing %s (%s%d)"), 
 419                                     Pkg
.Name(), "AddImplicitDepends", 1); 
 422    if (unlikely(AddImplicitDepends(Grp
, Pkg
, Ver
) == false)) 
 423       return _error
->Error(_("Error occurred while processing %s (%s%d)"), 
 424                            Pkg
.Name(), "AddImplicitDepends", 2); 
 426    // Read only a single record and return 
 433    /* Record the Description (it is not translated) */ 
 434    MD5SumValue CurMd5 
= List
.Description_md5(); 
 435    if (CurMd5
.Value().empty() == true) 
 437    std::string CurLang 
= List
.DescriptionLanguage(); 
 439    /* Before we add a new description we first search in the group for 
 440       a version with a description of the same MD5 - if so we reuse this 
 441       description group instead of creating our own for this version */ 
 442    for (pkgCache::PkgIterator P 
= Grp
.PackageList(); 
 443         P
.end() == false; P 
= Grp
.NextPkg(P
)) 
 445       for (pkgCache::VerIterator V 
= P
.VersionList(); 
 446            V
.end() == false; ++V
) 
 448          if (IsDuplicateDescription(V
.DescriptionList(), CurMd5
, "") == false) 
 450          Ver
->DescriptionList 
= V
->DescriptionList
; 
 455    // We haven't found reusable descriptions, so add the first description 
 456    pkgCache::DescIterator Desc 
= Ver
.DescriptionList(); 
 457    Dynamic
<pkgCache::DescIterator
> DynDesc(Desc
); 
 458    map_ptrloc 
*LastDesc 
= &Ver
->DescriptionList
; 
 461    map_ptrloc 
const descindex 
= NewDescription(Desc
, CurLang
, CurMd5
, *LastDesc
); 
 462    if (unlikely(descindex 
== 0 && _error
->PendingError())) 
 463       return _error
->Error(_("Error occurred while processing %s (%s%d)"), 
 464                            Pkg
.Name(), "NewDescription", 2); 
 465    if (oldMap 
!= Map
.Data()) 
 466        LastDesc 
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
; 
 467    *LastDesc 
= descindex
; 
 468    Desc
->ParentPkg 
= Pkg
.Index(); 
 470    if ((*LastDesc 
== 0 && _error
->PendingError()) || NewFileDesc(Desc
,List
) == false) 
 471       return _error
->Error(_("Error occurred while processing %s (%s%d)"), 
 472                            Pkg
.Name(), "NewFileDesc", 2); 
 478 // CacheGenerator::MergeFileProvides - Merge file provides              /*{{{*/ 
 479 // --------------------------------------------------------------------- 
 480 /* If we found any file depends while parsing the main list we need to  
 481    resolve them. Since it is undesired to load the entire list of files 
 482    into the cache as virtual packages we do a two stage effort. MergeList 
 483    identifies the file depends and this creates Provdies for them by 
 484    re-parsing all the indexs. */ 
 485 bool pkgCacheGenerator::MergeFileProvides(ListParser 
&List
) 
 489    unsigned int Counter 
= 0; 
 490    while (List
.Step() == true) 
 492       string PackageName 
= List
.Package(); 
 493       if (PackageName
.empty() == true) 
 495       string Version 
= List
.Version(); 
 496       if (Version
.empty() == true) 
 499       pkgCache::PkgIterator Pkg 
= Cache
.FindPkg(PackageName
); 
 500       Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
); 
 501       if (Pkg
.end() == true) 
 502          return _error
->Error(_("Error occurred while processing %s (%s%d)"), 
 503                                 PackageName
.c_str(), "FindPkg", 1); 
 505       if (Counter 
% 100 == 0 && Progress 
!= 0) 
 506          Progress
->Progress(List
.Offset()); 
 508       unsigned long Hash 
= List
.VersionHash(); 
 509       pkgCache::VerIterator Ver 
= Pkg
.VersionList(); 
 510       Dynamic
<pkgCache::VerIterator
> DynVer(Ver
); 
 511       for (; Ver
.end() == false; ++Ver
) 
 513          if (Ver
->Hash 
== Hash 
&& Version
.c_str() == Ver
.VerStr()) 
 515             if (List
.CollectFileProvides(Cache
,Ver
) == false) 
 516                return _error
->Error(_("Error occurred while processing %s (%s%d)"), 
 517                                     PackageName
.c_str(), "CollectFileProvides", 1); 
 522       if (Ver
.end() == true) 
 523          _error
->Warning(_("Package %s %s was not found while processing file dependencies"),PackageName
.c_str(),Version
.c_str()); 
 529 // CacheGenerator::NewGroup - Add a new group                           /*{{{*/ 
 530 // --------------------------------------------------------------------- 
 531 /* This creates a new group structure and adds it to the hash table */ 
 532 bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator 
&Grp
, const string 
&Name
) 
 534    Grp 
= Cache
.FindGrp(Name
); 
 535    if (Grp
.end() == false) 
 539    map_ptrloc 
const Group 
= AllocateInMap(sizeof(pkgCache::Group
)); 
 540    if (unlikely(Group 
== 0)) 
 543    Grp 
= pkgCache::GrpIterator(Cache
, Cache
.GrpP 
+ Group
); 
 544    map_ptrloc 
const idxName 
= WriteStringInMap(Name
); 
 545    if (unlikely(idxName 
== 0)) 
 549    // Insert it into the hash table 
 550    unsigned long const Hash 
= Cache
.Hash(Name
); 
 551    Grp
->Next 
= Cache
.HeaderP
->GrpHashTable
[Hash
]; 
 552    Cache
.HeaderP
->GrpHashTable
[Hash
] = Group
; 
 554    Grp
->ID 
= Cache
.HeaderP
->GroupCount
++; 
 558 // CacheGenerator::NewPackage - Add a new package                       /*{{{*/ 
 559 // --------------------------------------------------------------------- 
 560 /* This creates a new package structure and adds it to the hash table */ 
 561 bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator 
&Pkg
,const string 
&Name
, 
 562                                         const string 
&Arch
) { 
 563    pkgCache::GrpIterator Grp
; 
 564    Dynamic
<pkgCache::GrpIterator
> DynGrp(Grp
); 
 565    if (unlikely(NewGroup(Grp
, Name
) == false)) 
 568    Pkg 
= Grp
.FindPkg(Arch
); 
 569       if (Pkg
.end() == false) 
 573    map_ptrloc 
const Package 
= AllocateInMap(sizeof(pkgCache::Package
)); 
 574    if (unlikely(Package 
== 0)) 
 576    Pkg 
= pkgCache::PkgIterator(Cache
,Cache
.PkgP 
+ Package
); 
 578    // Insert the package into our package list 
 579    if (Grp
->FirstPackage 
== 0) // the group is new 
 581       // Insert it into the hash table 
 582       unsigned long const Hash 
= Cache
.Hash(Name
); 
 583       Pkg
->NextPackage 
= Cache
.HeaderP
->PkgHashTable
[Hash
]; 
 584       Cache
.HeaderP
->PkgHashTable
[Hash
] = Package
; 
 585       Grp
->FirstPackage 
= Package
; 
 587    else // Group the Packages together 
 589       // this package is the new last package 
 590       pkgCache::PkgIterator 
LastPkg(Cache
, Cache
.PkgP 
+ Grp
->LastPackage
); 
 591       Pkg
->NextPackage 
= LastPkg
->NextPackage
; 
 592       LastPkg
->NextPackage 
= Package
; 
 594    Grp
->LastPackage 
= Package
; 
 596    // Set the name, arch and the ID 
 597    Pkg
->Name 
= Grp
->Name
; 
 598    Pkg
->Group 
= Grp
.Index(); 
 599    // all is mapped to the native architecture 
 600    map_ptrloc 
const idxArch 
= (Arch 
== "all") ? Cache
.HeaderP
->Architecture 
: WriteUniqString(Arch
.c_str()); 
 601    if (unlikely(idxArch 
== 0)) 
 604    Pkg
->ID 
= Cache
.HeaderP
->PackageCount
++; 
 609 // CacheGenerator::AddImplicitDepends                                   /*{{{*/ 
 610 bool pkgCacheGenerator::AddImplicitDepends(pkgCache::GrpIterator 
&G
, 
 611                                            pkgCache::PkgIterator 
&P
, 
 612                                            pkgCache::VerIterator 
&V
) 
 614    // copy P.Arch() into a string here as a cache remap 
 615    // in NewDepends() later may alter the pointer location 
 616    string Arch 
= P
.Arch() == NULL 
? "" : P
.Arch(); 
 617    map_ptrloc 
*OldDepLast 
= NULL
; 
 618    /* MultiArch handling introduces a lot of implicit Dependencies: 
 619       - MultiArch: same → Co-Installable if they have the same version 
 620       - All others conflict with all other group members */ 
 621    bool const coInstall 
= ((V
->MultiArch 
& pkgCache::Version::Same
) == pkgCache::Version::Same
); 
 622    pkgCache::PkgIterator D 
= G
.PackageList(); 
 623    Dynamic
<pkgCache::PkgIterator
> DynD(D
); 
 624    for (; D
.end() != true; D 
= G
.NextPkg(D
)) 
 626       if (Arch 
== D
.Arch() || D
->VersionList 
== 0) 
 628       /* We allow only one installed arch at the time 
 629          per group, therefore each group member conflicts 
 630          with all other group members */ 
 631       if (coInstall 
== true) 
 633          // Replaces: ${self}:other ( << ${binary:Version}) 
 634          NewDepends(D
, V
, V
.VerStr(), 
 635                     pkgCache::Dep::Less
, pkgCache::Dep::Replaces
, 
 637          // Breaks: ${self}:other (!= ${binary:Version}) 
 638          NewDepends(D
, V
, V
.VerStr(), 
 639                     pkgCache::Dep::NotEquals
, pkgCache::Dep::DpkgBreaks
, 
 642          // Conflicts: ${self}:other 
 644                     pkgCache::Dep::NoOp
, pkgCache::Dep::Conflicts
, 
 650 bool pkgCacheGenerator::AddImplicitDepends(pkgCache::VerIterator 
&V
, 
 651                                            pkgCache::PkgIterator 
&D
) 
 653    /* MultiArch handling introduces a lot of implicit Dependencies: 
 654       - MultiArch: same → Co-Installable if they have the same version 
 655       - All others conflict with all other group members */ 
 656    map_ptrloc 
*OldDepLast 
= NULL
; 
 657    bool const coInstall 
= ((V
->MultiArch 
& pkgCache::Version::Same
) == pkgCache::Version::Same
); 
 658    if (coInstall 
== true) 
 660       // Replaces: ${self}:other ( << ${binary:Version}) 
 661       NewDepends(D
, V
, V
.VerStr(), 
 662                  pkgCache::Dep::Less
, pkgCache::Dep::Replaces
, 
 664       // Breaks: ${self}:other (!= ${binary:Version}) 
 665       NewDepends(D
, V
, V
.VerStr(), 
 666                  pkgCache::Dep::NotEquals
, pkgCache::Dep::DpkgBreaks
, 
 669       // Conflicts: ${self}:other 
 671                  pkgCache::Dep::NoOp
, pkgCache::Dep::Conflicts
, 
 678 // CacheGenerator::NewFileVer - Create a new File<->Version association /*{{{*/ 
 679 // --------------------------------------------------------------------- 
 681 bool pkgCacheGenerator::NewFileVer(pkgCache::VerIterator 
&Ver
, 
 684    if (CurrentFile 
== 0) 
 688    map_ptrloc 
const VerFile 
= AllocateInMap(sizeof(pkgCache::VerFile
)); 
 692    pkgCache::VerFileIterator 
VF(Cache
,Cache
.VerFileP 
+ VerFile
); 
 693    VF
->File 
= CurrentFile 
- Cache
.PkgFileP
; 
 695    // Link it to the end of the list 
 696    map_ptrloc 
*Last 
= &Ver
->FileList
; 
 697    for (pkgCache::VerFileIterator V 
= Ver
.FileList(); V
.end() == false; ++V
) 
 699    VF
->NextFile 
= *Last
; 
 702    VF
->Offset 
= List
.Offset(); 
 703    VF
->Size 
= List
.Size(); 
 704    if (Cache
.HeaderP
->MaxVerFileSize 
< VF
->Size
) 
 705       Cache
.HeaderP
->MaxVerFileSize 
= VF
->Size
; 
 706    Cache
.HeaderP
->VerFileCount
++; 
 711 // CacheGenerator::NewVersion - Create a new Version                    /*{{{*/ 
 712 // --------------------------------------------------------------------- 
 713 /* This puts a version structure in the linked list */ 
 714 unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator 
&Ver
, 
 715                                             const string 
&VerStr
, 
 719    map_ptrloc 
const Version 
= AllocateInMap(sizeof(pkgCache::Version
)); 
 724    Ver 
= pkgCache::VerIterator(Cache
,Cache
.VerP 
+ Version
); 
 726    Ver
->ID 
= Cache
.HeaderP
->VersionCount
++; 
 727    map_ptrloc 
const idxVerStr 
= WriteStringInMap(VerStr
); 
 728    if (unlikely(idxVerStr 
== 0)) 
 730    Ver
->VerStr 
= idxVerStr
; 
 735 // CacheGenerator::NewFileDesc - Create a new File<->Desc association   /*{{{*/ 
 736 // --------------------------------------------------------------------- 
 738 bool pkgCacheGenerator::NewFileDesc(pkgCache::DescIterator 
&Desc
, 
 741    if (CurrentFile 
== 0) 
 745    map_ptrloc 
const DescFile 
= AllocateInMap(sizeof(pkgCache::DescFile
)); 
 749    pkgCache::DescFileIterator 
DF(Cache
,Cache
.DescFileP 
+ DescFile
); 
 750    DF
->File 
= CurrentFile 
- Cache
.PkgFileP
; 
 752    // Link it to the end of the list 
 753    map_ptrloc 
*Last 
= &Desc
->FileList
; 
 754    for (pkgCache::DescFileIterator D 
= Desc
.FileList(); D
.end() == false; ++D
) 
 757    DF
->NextFile 
= *Last
; 
 760    DF
->Offset 
= List
.Offset(); 
 761    DF
->Size 
= List
.Size(); 
 762    if (Cache
.HeaderP
->MaxDescFileSize 
< DF
->Size
) 
 763       Cache
.HeaderP
->MaxDescFileSize 
= DF
->Size
; 
 764    Cache
.HeaderP
->DescFileCount
++; 
 769 // CacheGenerator::NewDescription - Create a new Description            /*{{{*/ 
 770 // --------------------------------------------------------------------- 
 771 /* This puts a description structure in the linked list */ 
 772 map_ptrloc 
pkgCacheGenerator::NewDescription(pkgCache::DescIterator 
&Desc
, 
 774                                             const MD5SumValue 
&md5sum
, 
 778    map_ptrloc 
const Description 
= AllocateInMap(sizeof(pkgCache::Description
)); 
 779    if (Description 
== 0) 
 783    Desc 
= pkgCache::DescIterator(Cache
,Cache
.DescP 
+ Description
); 
 784    Desc
->NextDesc 
= Next
; 
 785    Desc
->ID 
= Cache
.HeaderP
->DescriptionCount
++; 
 786    map_ptrloc 
const idxlanguage_code 
= WriteStringInMap(Lang
); 
 787    map_ptrloc 
const idxmd5sum 
= WriteStringInMap(md5sum
.Value()); 
 788    if (unlikely(idxlanguage_code 
== 0 || idxmd5sum 
== 0)) 
 790    Desc
->language_code 
= idxlanguage_code
; 
 791    Desc
->md5sum 
= idxmd5sum
; 
 796 // CacheGenerator::NewDepends - Create a dependency element             /*{{{*/ 
 797 // --------------------------------------------------------------------- 
 798 /* This creates a dependency element in the tree. It is linked to the 
 799    version and to the package that it is pointing to. */ 
 800 bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator 
&Pkg
, 
 801                                    pkgCache::VerIterator 
&Ver
, 
 802                                    string 
const &Version
, 
 803                                    unsigned int const &Op
, 
 804                                    unsigned int const &Type
, 
 805                                    map_ptrloc
* &OldDepLast
) 
 807    void const * const oldMap 
= Map
.Data(); 
 809    map_ptrloc 
const Dependency 
= AllocateInMap(sizeof(pkgCache::Dependency
)); 
 810    if (unlikely(Dependency 
== 0)) 
 814    pkgCache::DepIterator 
Dep(Cache
,Cache
.DepP 
+ Dependency
); 
 815    Dynamic
<pkgCache::DepIterator
> DynDep(Dep
); 
 816    Dep
->ParentVer 
= Ver
.Index(); 
 819    Dep
->ID 
= Cache
.HeaderP
->DependsCount
++; 
 821    // Probe the reverse dependency list for a version string that matches 
 822    if (Version
.empty() == false) 
 824 /*      for (pkgCache::DepIterator I = Pkg.RevDependsList(); I.end() == false; I++) 
 825          if (I->Version != 0 && I.TargetVer() == Version) 
 826             Dep->Version = I->Version;*/ 
 827       if (Dep
->Version 
== 0) { 
 828          map_ptrloc 
const index 
= WriteStringInMap(Version
); 
 829          if (unlikely(index 
== 0)) 
 831          Dep
->Version 
= index
; 
 835    // Link it to the package 
 836    Dep
->Package 
= Pkg
.Index(); 
 837    Dep
->NextRevDepends 
= Pkg
->RevDepends
; 
 838    Pkg
->RevDepends 
= Dep
.Index(); 
 840    // Do we know where to link the Dependency to? 
 841    if (OldDepLast 
== NULL
) 
 843       OldDepLast 
= &Ver
->DependsList
; 
 844       for (pkgCache::DepIterator D 
= Ver
.DependsList(); D
.end() == false; ++D
) 
 845          OldDepLast 
= &D
->NextDepends
; 
 846    } else if (oldMap 
!= Map
.Data()) 
 847       OldDepLast 
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
; 
 849    Dep
->NextDepends 
= *OldDepLast
; 
 850    *OldDepLast 
= Dep
.Index(); 
 851    OldDepLast 
= &Dep
->NextDepends
; 
 856 // ListParser::NewDepends - Create the environment for a new dependency /*{{{*/ 
 857 // --------------------------------------------------------------------- 
 858 /* This creates a Group and the Package to link this dependency to if 
 859    needed and handles also the caching of the old endpoint */ 
 860 bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator 
&Ver
, 
 861                                                const string 
&PackageName
, 
 863                                                const string 
&Version
, 
 867    pkgCache::GrpIterator Grp
; 
 868    Dynamic
<pkgCache::GrpIterator
> DynGrp(Grp
); 
 869    if (unlikely(Owner
->NewGroup(Grp
, PackageName
) == false)) 
 872    // Locate the target package 
 873    pkgCache::PkgIterator Pkg 
= Grp
.FindPkg(Arch
); 
 874    Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
); 
 875    if (Pkg
.end() == true) { 
 876       if (unlikely(Owner
->NewPackage(Pkg
, PackageName
, Arch
) == false)) 
 880    // Is it a file dependency? 
 881    if (unlikely(PackageName
[0] == '/')) 
 882       FoundFileDeps 
= true; 
 884    /* Caching the old end point speeds up generation substantially */ 
 885    if (OldDepVer 
!= Ver
) { 
 890    return Owner
->NewDepends(Pkg
, Ver
, Version
, Op
, Type
, OldDepLast
); 
 893 // ListParser::NewProvides - Create a Provides element                  /*{{{*/ 
 894 // --------------------------------------------------------------------- 
 896 bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator 
&Ver
, 
 897                                                 const string 
&PkgName
, 
 898                                                 const string 
&PkgArch
, 
 899                                                 const string 
&Version
) 
 901    pkgCache 
&Cache 
= Owner
->Cache
; 
 903    // We do not add self referencing provides 
 904    if (Ver
.ParentPkg().Name() == PkgName 
&& (PkgArch 
== Ver
.ParentPkg().Arch() || 
 905         (PkgArch 
== "all" && strcmp((Cache
.StrP 
+ Cache
.HeaderP
->Architecture
), Ver
.ParentPkg().Arch()) == 0))) 
 909    map_ptrloc 
const Provides 
= Owner
->AllocateInMap(sizeof(pkgCache::Provides
)); 
 910    if (unlikely(Provides 
== 0)) 
 912    Cache
.HeaderP
->ProvidesCount
++; 
 915    pkgCache::PrvIterator 
Prv(Cache
,Cache
.ProvideP 
+ Provides
,Cache
.PkgP
); 
 916    Dynamic
<pkgCache::PrvIterator
> DynPrv(Prv
); 
 917    Prv
->Version 
= Ver
.Index(); 
 918    Prv
->NextPkgProv 
= Ver
->ProvidesList
; 
 919    Ver
->ProvidesList 
= Prv
.Index(); 
 920    if (Version
.empty() == false && unlikely((Prv
->ProvideVersion 
= WriteString(Version
)) == 0)) 
 923    // Locate the target package 
 924    pkgCache::PkgIterator Pkg
; 
 925    Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
); 
 926    if (unlikely(Owner
->NewPackage(Pkg
,PkgName
, PkgArch
) == false)) 
 929    // Link it to the package 
 930    Prv
->ParentPkg 
= Pkg
.Index(); 
 931    Prv
->NextProvides 
= Pkg
->ProvidesList
; 
 932    Pkg
->ProvidesList 
= Prv
.Index(); 
 937 // CacheGenerator::SelectFile - Select the current file being parsed    /*{{{*/ 
 938 // --------------------------------------------------------------------- 
 939 /* This is used to select which file is to be associated with all newly 
 940    added versions. The caller is responsible for setting the IMS fields. */ 
 941 bool pkgCacheGenerator::SelectFile(const string 
&File
,const string 
&Site
, 
 942                                    const pkgIndexFile 
&Index
, 
 945    // Get some space for the structure 
 946    map_ptrloc 
const idxFile 
= AllocateInMap(sizeof(*CurrentFile
)); 
 947    if (unlikely(idxFile 
== 0)) 
 949    CurrentFile 
= Cache
.PkgFileP 
+ idxFile
; 
 952    map_ptrloc 
const idxFileName 
= WriteStringInMap(File
); 
 953    map_ptrloc 
const idxSite 
= WriteUniqString(Site
); 
 954    if (unlikely(idxFileName 
== 0 || idxSite 
== 0)) 
 956    CurrentFile
->FileName 
= idxFileName
; 
 957    CurrentFile
->Site 
= idxSite
; 
 958    CurrentFile
->NextFile 
= Cache
.HeaderP
->FileList
; 
 959    CurrentFile
->Flags 
= Flags
; 
 960    CurrentFile
->ID 
= Cache
.HeaderP
->PackageFileCount
; 
 961    map_ptrloc 
const idxIndexType 
= WriteUniqString(Index
.GetType()->Label
); 
 962    if (unlikely(idxIndexType 
== 0)) 
 964    CurrentFile
->IndexType 
= idxIndexType
; 
 966    Cache
.HeaderP
->FileList 
= CurrentFile 
- Cache
.PkgFileP
; 
 967    Cache
.HeaderP
->PackageFileCount
++; 
 970       Progress
->SubProgress(Index
.Size()); 
 974 // CacheGenerator::WriteUniqueString - Insert a unique string           /*{{{*/ 
 975 // --------------------------------------------------------------------- 
 976 /* This is used to create handles to strings. Given the same text it 
 977    always returns the same number */ 
 978 unsigned long pkgCacheGenerator::WriteUniqString(const char *S
, 
 981    /* We use a very small transient hash table here, this speeds up generation 
 982       by a fair amount on slower machines */ 
 983    pkgCache::StringItem 
*&Bucket 
= UniqHash
[(S
[0]*5 + S
[1]) % _count(UniqHash
)]; 
 985        stringcmp(S
,S
+Size
,Cache
.StrP 
+ Bucket
->String
) == 0) 
 986       return Bucket
->String
; 
 988    // Search for an insertion point 
 989    pkgCache::StringItem 
*I 
= Cache
.StringItemP 
+ Cache
.HeaderP
->StringList
; 
 991    map_ptrloc 
*Last 
= &Cache
.HeaderP
->StringList
; 
 992    for (; I 
!= Cache
.StringItemP
; Last 
= &I
->NextItem
,  
 993         I 
= Cache
.StringItemP 
+ I
->NextItem
) 
 995       Res 
= stringcmp(S
,S
+Size
,Cache
.StrP 
+ I
->String
); 
1008    void const * const oldMap 
= Map
.Data(); 
1009    map_ptrloc 
const Item 
= AllocateInMap(sizeof(pkgCache::StringItem
)); 
1013    map_ptrloc 
const idxString 
= WriteStringInMap(S
,Size
); 
1014    if (unlikely(idxString 
== 0)) 
1016    if (oldMap 
!= Map
.Data()) { 
1017       Last 
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
; 
1018       I 
+= (pkgCache::StringItem
*) Map
.Data() - (pkgCache::StringItem
*) oldMap
; 
1022    // Fill in the structure 
1023    pkgCache::StringItem 
*ItemP 
= Cache
.StringItemP 
+ Item
; 
1024    ItemP
->NextItem 
= I 
- Cache
.StringItemP
; 
1025    ItemP
->String 
= idxString
; 
1028    return ItemP
->String
; 
1031 // CheckValidity - Check that a cache is up-to-date                     /*{{{*/ 
1032 // --------------------------------------------------------------------- 
1033 /* This just verifies that each file in the list of index files exists, 
1034    has matching attributes with the cache and the cache does not have 
1036 static bool CheckValidity(const string 
&CacheFile
,  
1037                           pkgSourceList 
&List
, 
1042    bool const Debug 
= _config
->FindB("Debug::pkgCacheGen", false); 
1043    // No file, certainly invalid 
1044    if (CacheFile
.empty() == true || FileExists(CacheFile
) == false) 
1047          std::clog 
<< "CacheFile doesn't exist" << std::endl
; 
1051    if (List
.GetLastModifiedTime() > GetModificationTime(CacheFile
)) 
1054          std::clog 
<< "sources.list is newer than the cache" << std::endl
; 
1059    FileFd 
CacheF(CacheFile
,FileFd::ReadOnly
); 
1060    SPtr
<MMap
> Map 
= new MMap(CacheF
,0); 
1061    pkgCache 
Cache(Map
); 
1062    if (_error
->PendingError() == true || Map
->Size() == 0) 
1065          std::clog 
<< "Errors are pending or Map is empty()" << std::endl
; 
1070    /* Now we check every index file, see if it is in the cache, 
1071       verify the IMS data and check that it is on the disk too.. */ 
1072    SPtrArray
<bool> Visited 
= new bool[Cache
.HeaderP
->PackageFileCount
]; 
1073    memset(Visited
,0,sizeof(*Visited
)*Cache
.HeaderP
->PackageFileCount
); 
1074    for (; Start 
!= End
; ++Start
) 
1077          std::clog 
<< "Checking PkgFile " << (*Start
)->Describe() << ": "; 
1078       if ((*Start
)->HasPackages() == false) 
1081             std::clog 
<< "Has NO packages" << std::endl
; 
1085       if ((*Start
)->Exists() == false) 
1087 #if 0 // mvo: we no longer give a message here (Default Sources spec) 
1088          _error
->WarningE("stat",_("Couldn't stat source package list %s"), 
1089                           (*Start
)->Describe().c_str()); 
1092             std::clog 
<< "file doesn't exist" << std::endl
; 
1096       // FindInCache is also expected to do an IMS check. 
1097       pkgCache::PkgFileIterator File 
= (*Start
)->FindInCache(Cache
); 
1098       if (File
.end() == true) 
1101             std::clog 
<< "FindInCache returned end-Pointer" << std::endl
; 
1105       Visited
[File
->ID
] = true; 
1107          std::clog 
<< "with ID " << File
->ID 
<< " is valid" << std::endl
; 
1110    for (unsigned I 
= 0; I 
!= Cache
.HeaderP
->PackageFileCount
; I
++) 
1111       if (Visited
[I
] == false) 
1114             std::clog 
<< "File with ID" << I 
<< " wasn't visited" << std::endl
; 
1118    if (_error
->PendingError() == true) 
1122          std::clog 
<< "Validity failed because of pending errors:" << std::endl
; 
1123          _error
->DumpErrors(); 
1130       *OutMap 
= Map
.UnGuard(); 
1134 // ComputeSize - Compute the total size of a bunch of files             /*{{{*/ 
1135 // --------------------------------------------------------------------- 
1136 /* Size is kind of an abstract notion that is only used for the progress 
1138 static unsigned long ComputeSize(FileIterator Start
,FileIterator End
) 
1140    unsigned long TotalSize 
= 0; 
1141    for (; Start 
!= End
; ++Start
) 
1143       if ((*Start
)->HasPackages() == false) 
1145       TotalSize 
+= (*Start
)->Size(); 
1150 // BuildCache - Merge the list of index files into the cache            /*{{{*/ 
1151 // --------------------------------------------------------------------- 
1153 static bool BuildCache(pkgCacheGenerator 
&Gen
, 
1154                        OpProgress 
*Progress
, 
1155                        unsigned long &CurrentSize
,unsigned long TotalSize
, 
1156                        FileIterator Start
, FileIterator End
) 
1159    for (I 
= Start
; I 
!= End
; ++I
) 
1161       if ((*I
)->HasPackages() == false) 
1164       if ((*I
)->Exists() == false) 
1167       if ((*I
)->FindInCache(Gen
.GetCache()).end() == false) 
1169          _error
->Warning("Duplicate sources.list entry %s", 
1170                          (*I
)->Describe().c_str()); 
1174       unsigned long Size 
= (*I
)->Size(); 
1175       if (Progress 
!= NULL
) 
1176          Progress
->OverallProgress(CurrentSize
,TotalSize
,Size
,_("Reading package lists")); 
1177       CurrentSize 
+= Size
; 
1179       if ((*I
)->Merge(Gen
,Progress
) == false) 
1183    if (Gen
.HasFileDeps() == true) 
1185       if (Progress 
!= NULL
) 
1187       TotalSize 
= ComputeSize(Start
, End
); 
1189       for (I 
= Start
; I 
!= End
; ++I
) 
1191          unsigned long Size 
= (*I
)->Size(); 
1192          if (Progress 
!= NULL
) 
1193             Progress
->OverallProgress(CurrentSize
,TotalSize
,Size
,_("Collecting File Provides")); 
1194          CurrentSize 
+= Size
; 
1195          if ((*I
)->MergeFileProvides(Gen
,Progress
) == false) 
1203 // CacheGenerator::CreateDynamicMMap - load an mmap with configuration options  /*{{{*/ 
1204 DynamicMMap
* pkgCacheGenerator::CreateDynamicMMap(FileFd 
*CacheF
, unsigned long Flags
) { 
1205    unsigned long const MapStart 
= _config
->FindI("APT::Cache-Start", 24*1024*1024); 
1206    unsigned long const MapGrow 
= _config
->FindI("APT::Cache-Grow", 1*1024*1024); 
1207    unsigned long const MapLimit 
= _config
->FindI("APT::Cache-Limit", 0); 
1208    Flags 
|= MMap::Moveable
; 
1209    if (_config
->FindB("APT::Cache-Fallback", false) == true) 
1210       Flags 
|= MMap::Fallback
; 
1212       return new DynamicMMap(*CacheF
, Flags
, MapStart
, MapGrow
, MapLimit
); 
1214       return new DynamicMMap(Flags
, MapStart
, MapGrow
, MapLimit
); 
1217 // CacheGenerator::MakeStatusCache - Construct the status cache         /*{{{*/ 
1218 // --------------------------------------------------------------------- 
1219 /* This makes sure that the status cache (the cache that has all  
1220    index files from the sources list and all local ones) is ready 
1221    to be mmaped. If OutMap is not zero then a MMap object representing 
1222    the cache will be stored there. This is pretty much mandetory if you 
1223    are using AllowMem. AllowMem lets the function be run as non-root 
1224    where it builds the cache 'fast' into a memory buffer. */ 
1225 __deprecated 
bool pkgMakeStatusCache(pkgSourceList 
&List
,OpProgress 
&Progress
, 
1226                         MMap 
**OutMap
, bool AllowMem
) 
1227    { return pkgCacheGenerator::MakeStatusCache(List
, &Progress
, OutMap
, AllowMem
); } 
1228 bool pkgCacheGenerator::MakeStatusCache(pkgSourceList 
&List
,OpProgress 
*Progress
, 
1229                         MMap 
**OutMap
,bool AllowMem
) 
1231    bool const Debug 
= _config
->FindB("Debug::pkgCacheGen", false); 
1233    std::vector
<pkgIndexFile 
*> Files
; 
1234    for (std::vector
<metaIndex 
*>::const_iterator i 
= List
.begin(); 
1238       std::vector 
<pkgIndexFile 
*> *Indexes 
= (*i
)->GetIndexFiles(); 
1239       for (std::vector
<pkgIndexFile 
*>::const_iterator j 
= Indexes
->begin(); 
1240            j 
!= Indexes
->end(); 
1242          Files
.push_back (*j
); 
1245    unsigned long const EndOfSource 
= Files
.size(); 
1246    if (_system
->AddStatusFiles(Files
) == false) 
1249    // Decide if we can write to the files.. 
1250    string 
const CacheFile 
= _config
->FindFile("Dir::Cache::pkgcache"); 
1251    string 
const SrcCacheFile 
= _config
->FindFile("Dir::Cache::srcpkgcache"); 
1253    // ensure the cache directory exists 
1254    if (CacheFile
.empty() == false || SrcCacheFile
.empty() == false) 
1256       string dir 
= _config
->FindDir("Dir::Cache"); 
1257       size_t const len 
= dir
.size(); 
1258       if (len 
> 5 && dir
.find("/apt/", len 
- 6, 5) == len 
- 5) 
1259          dir 
= dir
.substr(0, len 
- 5); 
1260       if (CacheFile
.empty() == false) 
1261          CreateDirectory(dir
, flNotFile(CacheFile
)); 
1262       if (SrcCacheFile
.empty() == false) 
1263          CreateDirectory(dir
, flNotFile(SrcCacheFile
)); 
1266    // Decide if we can write to the cache 
1267    bool Writeable 
= false; 
1268    if (CacheFile
.empty() == false) 
1269       Writeable 
= access(flNotFile(CacheFile
).c_str(),W_OK
) == 0; 
1271       if (SrcCacheFile
.empty() == false) 
1272          Writeable 
= access(flNotFile(SrcCacheFile
).c_str(),W_OK
) == 0; 
1274       std::clog 
<< "Do we have write-access to the cache files? " << (Writeable 
? "YES" : "NO") << std::endl
; 
1276    if (Writeable 
== false && AllowMem 
== false && CacheFile
.empty() == false) 
1277       return _error
->Error(_("Unable to write to %s"),flNotFile(CacheFile
).c_str()); 
1279    if (Progress 
!= NULL
) 
1280       Progress
->OverallProgress(0,1,1,_("Reading package lists")); 
1282    // Cache is OK, Fin. 
1283    if (CheckValidity(CacheFile
, List
, Files
.begin(),Files
.end(),OutMap
) == true) 
1285       if (Progress 
!= NULL
) 
1286          Progress
->OverallProgress(1,1,1,_("Reading package lists")); 
1288          std::clog 
<< "pkgcache.bin is valid - no need to build anything" << std::endl
; 
1291    else if (Debug 
== true) 
1292          std::clog 
<< "pkgcache.bin is NOT valid" << std::endl
; 
1294    /* At this point we know we need to reconstruct the package cache, 
1296    SPtr
<FileFd
> CacheF
; 
1297    SPtr
<DynamicMMap
> Map
; 
1298    if (Writeable 
== true && CacheFile
.empty() == false) 
1300       _error
->PushToStack(); 
1301       unlink(CacheFile
.c_str()); 
1302       CacheF 
= new FileFd(CacheFile
,FileFd::WriteAtomic
); 
1303       fchmod(CacheF
->Fd(),0644); 
1304       Map 
= CreateDynamicMMap(CacheF
, MMap::Public
); 
1305       if (_error
->PendingError() == true) 
1307          delete CacheF
.UnGuard(); 
1308          delete Map
.UnGuard(); 
1310             std::clog 
<< "Open filebased MMap FAILED" << std::endl
; 
1312          if (AllowMem 
== false) 
1314             _error
->MergeWithStack(); 
1317          _error
->RevertToStack(); 
1321          _error
->MergeWithStack(); 
1323             std::clog 
<< "Open filebased MMap" << std::endl
; 
1326    if (Writeable 
== false || CacheFile
.empty() == true) 
1328       // Just build it in memory.. 
1329       Map 
= CreateDynamicMMap(NULL
); 
1331          std::clog 
<< "Open memory Map (not filebased)" << std::endl
; 
1334    // Lets try the source cache. 
1335    unsigned long CurrentSize 
= 0; 
1336    unsigned long TotalSize 
= 0; 
1337    if (CheckValidity(SrcCacheFile
, List
, Files
.begin(), 
1338                      Files
.begin()+EndOfSource
) == true) 
1341          std::clog 
<< "srcpkgcache.bin is valid - populate MMap with it." << std::endl
; 
1342       // Preload the map with the source cache 
1343       FileFd 
SCacheF(SrcCacheFile
,FileFd::ReadOnly
); 
1344       unsigned long const alloc 
= Map
->RawAllocate(SCacheF
.Size()); 
1345       if ((alloc 
== 0 && _error
->PendingError()) 
1346                 || SCacheF
.Read((unsigned char *)Map
->Data() + alloc
, 
1347                                 SCacheF
.Size()) == false) 
1350       TotalSize 
= ComputeSize(Files
.begin()+EndOfSource
,Files
.end()); 
1352       // Build the status cache 
1353       pkgCacheGenerator 
Gen(Map
.Get(),Progress
); 
1354       if (_error
->PendingError() == true) 
1356       if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
, 
1357                      Files
.begin()+EndOfSource
,Files
.end()) == false) 
1363          std::clog 
<< "srcpkgcache.bin is NOT valid - rebuild" << std::endl
; 
1364       TotalSize 
= ComputeSize(Files
.begin(),Files
.end()); 
1366       // Build the source cache 
1367       pkgCacheGenerator 
Gen(Map
.Get(),Progress
); 
1368       if (_error
->PendingError() == true) 
1370       if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
, 
1371                      Files
.begin(),Files
.begin()+EndOfSource
) == false) 
1375       if (Writeable 
== true && SrcCacheFile
.empty() == false) 
1377          FileFd 
SCacheF(SrcCacheFile
,FileFd::WriteAtomic
); 
1378          if (_error
->PendingError() == true) 
1381          fchmod(SCacheF
.Fd(),0644); 
1383          // Write out the main data 
1384          if (SCacheF
.Write(Map
->Data(),Map
->Size()) == false) 
1385             return _error
->Error(_("IO Error saving source cache")); 
1388          // Write out the proper header 
1389          Gen
.GetCache().HeaderP
->Dirty 
= false; 
1390          if (SCacheF
.Seek(0) == false || 
1391              SCacheF
.Write(Map
->Data(),sizeof(*Gen
.GetCache().HeaderP
)) == false) 
1392             return _error
->Error(_("IO Error saving source cache")); 
1393          Gen
.GetCache().HeaderP
->Dirty 
= true; 
1397       // Build the status cache 
1398       if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
, 
1399                      Files
.begin()+EndOfSource
,Files
.end()) == false) 
1403       std::clog 
<< "Caches are ready for shipping" << std::endl
; 
1405    if (_error
->PendingError() == true) 
1411          delete Map
.UnGuard(); 
1412          *OutMap 
= new MMap(*CacheF
,0); 
1416          *OutMap 
= Map
.UnGuard(); 
1423 // CacheGenerator::MakeOnlyStatusCache - Build only a status files cache/*{{{*/ 
1424 // --------------------------------------------------------------------- 
1426 __deprecated 
bool pkgMakeOnlyStatusCache(OpProgress 
&Progress
,DynamicMMap 
**OutMap
) 
1427    { return pkgCacheGenerator::MakeOnlyStatusCache(&Progress
, OutMap
); } 
1428 bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress 
*Progress
,DynamicMMap 
**OutMap
) 
1430    std::vector
<pkgIndexFile 
*> Files
; 
1431    unsigned long EndOfSource 
= Files
.size(); 
1432    if (_system
->AddStatusFiles(Files
) == false) 
1435    SPtr
<DynamicMMap
> Map 
= CreateDynamicMMap(NULL
); 
1436    unsigned long CurrentSize 
= 0; 
1437    unsigned long TotalSize 
= 0; 
1439    TotalSize 
= ComputeSize(Files
.begin()+EndOfSource
,Files
.end()); 
1441    // Build the status cache 
1442    if (Progress 
!= NULL
) 
1443       Progress
->OverallProgress(0,1,1,_("Reading package lists")); 
1444    pkgCacheGenerator 
Gen(Map
.Get(),Progress
); 
1445    if (_error
->PendingError() == true) 
1447    if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
, 
1448                   Files
.begin()+EndOfSource
,Files
.end()) == false) 
1451    if (_error
->PendingError() == true) 
1453    *OutMap 
= Map
.UnGuard(); 
1458 // IsDuplicateDescription                                               /*{{{*/ 
1459 static bool IsDuplicateDescription(pkgCache::DescIterator Desc
, 
1460                             MD5SumValue 
const &CurMd5
, std::string 
const &CurLang
) 
1462    // Descriptions in the same link-list have all the same md5 
1463    if (Desc
.end() == true || MD5SumValue(Desc
.md5()) != CurMd5
) 
1465    for (; Desc
.end() == false; ++Desc
) 
1466       if (Desc
.LanguageCode() == CurLang
) 
1471 // CacheGenerator::FinishCache                                          /*{{{*/ 
1472 bool pkgCacheGenerator::FinishCache(OpProgress 
*Progress
)