]>
git.saurik.com Git - apt.git/blob - apt-pkg/pkgcachegen.cc
3545517fe67c03922c67b142b84a8fd0c2e46986
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 vector
<pkgIndexFile
*>::iterator FileIterator
;
39 template <typename Iter
> std::vector
<Iter
*> pkgCacheGenerator::Dynamic
<Iter
>::toReMap
;
41 bool IsDuplicateDescription(pkgCache::DescIterator Desc
,
42 MD5SumValue
const &CurMd5
, std::string
const &CurLang
);
44 // CacheGenerator::pkgCacheGenerator - Constructor /*{{{*/
45 // ---------------------------------------------------------------------
46 /* We set the dirty flag and make sure that is written to the disk */
47 pkgCacheGenerator::pkgCacheGenerator(DynamicMMap
*pMap
,OpProgress
*Prog
) :
48 Map(*pMap
), Cache(pMap
,false), Progress(Prog
),
52 memset(UniqHash
,0,sizeof(UniqHash
));
54 if (_error
->PendingError() == true)
59 // Setup the map interface..
60 Cache
.HeaderP
= (pkgCache::Header
*)Map
.Data();
61 if (Map
.RawAllocate(sizeof(pkgCache::Header
)) == 0 && _error
->PendingError() == true)
64 Map
.UsePools(*Cache
.HeaderP
->Pools
,sizeof(Cache
.HeaderP
->Pools
)/sizeof(Cache
.HeaderP
->Pools
[0]));
67 *Cache
.HeaderP
= pkgCache::Header();
68 map_ptrloc
const idxVerSysName
= WriteStringInMap(_system
->VS
->Label
);
69 Cache
.HeaderP
->VerSysName
= idxVerSysName
;
70 map_ptrloc
const idxArchitecture
= WriteStringInMap(_config
->Find("APT::Architecture"));
71 Cache
.HeaderP
->Architecture
= idxArchitecture
;
72 if (unlikely(idxVerSysName
== 0 || idxArchitecture
== 0))
78 // Map directly from the existing file
80 Map
.UsePools(*Cache
.HeaderP
->Pools
,sizeof(Cache
.HeaderP
->Pools
)/sizeof(Cache
.HeaderP
->Pools
[0]));
81 if (Cache
.VS
!= _system
->VS
)
83 _error
->Error(_("Cache has an incompatible versioning system"));
88 Cache
.HeaderP
->Dirty
= true;
89 Map
.Sync(0,sizeof(pkgCache::Header
));
92 // CacheGenerator::~pkgCacheGenerator - Destructor /*{{{*/
93 // ---------------------------------------------------------------------
94 /* We sync the data then unset the dirty flag in two steps so as to
95 advoid a problem during a crash */
96 pkgCacheGenerator::~pkgCacheGenerator()
98 if (_error
->PendingError() == true)
100 if (Map
.Sync() == false)
103 Cache
.HeaderP
->Dirty
= false;
104 Cache
.HeaderP
->CacheFileSize
= Map
.Size();
105 Map
.Sync(0,sizeof(pkgCache::Header
));
108 void pkgCacheGenerator::ReMap(void const * const oldMap
, void const * const newMap
) {/*{{{*/
109 if (oldMap
== newMap
)
112 if (_config
->FindB("Debug::pkgCacheGen", false))
113 std::clog
<< "Remaping from " << oldMap
<< " to " << newMap
<< std::endl
;
117 CurrentFile
+= (pkgCache::PackageFile
*) newMap
- (pkgCache::PackageFile
*) oldMap
;
119 for (size_t i
= 0; i
< _count(UniqHash
); ++i
)
120 if (UniqHash
[i
] != 0)
121 UniqHash
[i
] += (pkgCache::StringItem
*) newMap
- (pkgCache::StringItem
*) oldMap
;
123 for (std::vector
<pkgCache::GrpIterator
*>::const_iterator i
= Dynamic
<pkgCache::GrpIterator
>::toReMap
.begin();
124 i
!= Dynamic
<pkgCache::GrpIterator
>::toReMap
.end(); ++i
)
125 (*i
)->ReMap(oldMap
, newMap
);
126 for (std::vector
<pkgCache::PkgIterator
*>::const_iterator i
= Dynamic
<pkgCache::PkgIterator
>::toReMap
.begin();
127 i
!= Dynamic
<pkgCache::PkgIterator
>::toReMap
.end(); ++i
)
128 (*i
)->ReMap(oldMap
, newMap
);
129 for (std::vector
<pkgCache::VerIterator
*>::const_iterator i
= Dynamic
<pkgCache::VerIterator
>::toReMap
.begin();
130 i
!= Dynamic
<pkgCache::VerIterator
>::toReMap
.end(); ++i
)
131 (*i
)->ReMap(oldMap
, newMap
);
132 for (std::vector
<pkgCache::DepIterator
*>::const_iterator i
= Dynamic
<pkgCache::DepIterator
>::toReMap
.begin();
133 i
!= Dynamic
<pkgCache::DepIterator
>::toReMap
.end(); ++i
)
134 (*i
)->ReMap(oldMap
, newMap
);
135 for (std::vector
<pkgCache::DescIterator
*>::const_iterator i
= Dynamic
<pkgCache::DescIterator
>::toReMap
.begin();
136 i
!= Dynamic
<pkgCache::DescIterator
>::toReMap
.end(); ++i
)
137 (*i
)->ReMap(oldMap
, newMap
);
138 for (std::vector
<pkgCache::PrvIterator
*>::const_iterator i
= Dynamic
<pkgCache::PrvIterator
>::toReMap
.begin();
139 i
!= Dynamic
<pkgCache::PrvIterator
>::toReMap
.end(); ++i
)
140 (*i
)->ReMap(oldMap
, newMap
);
141 for (std::vector
<pkgCache::PkgFileIterator
*>::const_iterator i
= Dynamic
<pkgCache::PkgFileIterator
>::toReMap
.begin();
142 i
!= Dynamic
<pkgCache::PkgFileIterator
>::toReMap
.end(); ++i
)
143 (*i
)->ReMap(oldMap
, newMap
);
145 // CacheGenerator::WriteStringInMap /*{{{*/
146 map_ptrloc
pkgCacheGenerator::WriteStringInMap(const char *String
,
147 const unsigned long &Len
) {
148 void const * const oldMap
= Map
.Data();
149 map_ptrloc
const index
= Map
.WriteString(String
, Len
);
151 ReMap(oldMap
, Map
.Data());
155 // CacheGenerator::WriteStringInMap /*{{{*/
156 map_ptrloc
pkgCacheGenerator::WriteStringInMap(const char *String
) {
157 void const * const oldMap
= Map
.Data();
158 map_ptrloc
const index
= Map
.WriteString(String
);
160 ReMap(oldMap
, Map
.Data());
164 map_ptrloc
pkgCacheGenerator::AllocateInMap(const unsigned long &size
) {/*{{{*/
165 void const * const oldMap
= Map
.Data();
166 map_ptrloc
const index
= Map
.Allocate(size
);
168 ReMap(oldMap
, Map
.Data());
172 // CacheGenerator::MergeList - Merge the package list /*{{{*/
173 // ---------------------------------------------------------------------
174 /* This provides the generation of the entries in the cache. Each loop
175 goes through a single package record from the underlying parse engine. */
176 bool pkgCacheGenerator::MergeList(ListParser
&List
,
177 pkgCache::VerIterator
*OutVer
)
181 unsigned int Counter
= 0;
182 while (List
.Step() == true)
184 string
const PackageName
= List
.Package();
185 if (PackageName
.empty() == true)
189 if (Counter
% 100 == 0 && Progress
!= 0)
190 Progress
->Progress(List
.Offset());
192 string Arch
= List
.Architecture();
193 string
const Version
= List
.Version();
194 if (Version
.empty() == true && Arch
.empty() == true)
196 if (MergeListGroup(List
, PackageName
) == false)
200 if (Arch
.empty() == true)
201 Arch
= _config
->Find("APT::Architecture");
203 // Get a pointer to the package structure
204 pkgCache::PkgIterator Pkg
;
205 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
206 if (NewPackage(Pkg
, PackageName
, Arch
) == false)
207 return _error
->Error(_("Error occurred while processing %s (NewPackage)"),PackageName
.c_str());
210 if (Version
.empty() == true)
212 if (MergeListPackage(List
, Pkg
) == false)
217 if (MergeListVersion(List
, Pkg
, Version
, OutVer
) == false)
223 FoundFileDeps
|= List
.HasFileDeps();
228 if (Cache
.HeaderP
->PackageCount
>= (1ULL<<sizeof(Cache
.PkgP
->ID
)*8)-1)
229 return _error
->Error(_("Wow, you exceeded the number of package "
230 "names this APT is capable of."));
231 if (Cache
.HeaderP
->VersionCount
>= (1ULL<<(sizeof(Cache
.VerP
->ID
)*8))-1)
232 return _error
->Error(_("Wow, you exceeded the number of versions "
233 "this APT is capable of."));
234 if (Cache
.HeaderP
->DescriptionCount
>= (1ULL<<(sizeof(Cache
.DescP
->ID
)*8))-1)
235 return _error
->Error(_("Wow, you exceeded the number of descriptions "
236 "this APT is capable of."));
237 if (Cache
.HeaderP
->DependsCount
>= (1ULL<<(sizeof(Cache
.DepP
->ID
)*8))-1ULL)
238 return _error
->Error(_("Wow, you exceeded the number of dependencies "
239 "this APT is capable of."));
241 FoundFileDeps
|= List
.HasFileDeps();
244 // CacheGenerator::MergeListGroup /*{{{*/
245 bool pkgCacheGenerator::MergeListGroup(ListParser
&List
, std::string
const &GrpName
)
247 pkgCache::GrpIterator Grp
= Cache
.FindGrp(GrpName
);
248 // a group has no data on it's own, only packages have it but these
249 // stanzas like this come from Translation- files to add descriptions,
250 // but without a version we don't need a description for it…
251 if (Grp
.end() == true)
253 Dynamic
<pkgCache::GrpIterator
> DynGrp(Grp
);
255 pkgCache::PkgIterator Pkg
;
256 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
257 for (Pkg
= Grp
.PackageList(); Pkg
.end() == false; Pkg
= Grp
.NextPkg(Pkg
))
258 if (MergeListPackage(List
, Pkg
) == false)
264 // CacheGenerator::MergeListPackage /*{{{*/
265 bool pkgCacheGenerator::MergeListPackage(ListParser
&List
, pkgCache::PkgIterator
&Pkg
)
267 // we first process the package, then the descriptions
268 // (for deb this package processing is in fact a no-op)
269 pkgCache::VerIterator
Ver(Cache
);
270 Dynamic
<pkgCache::VerIterator
> DynVer(Ver
);
271 if (List
.UsePackage(Pkg
, Ver
) == false)
272 return _error
->Error(_("Error occurred while processing %s (UsePackage1)"),
275 // Find the right version to write the description
276 MD5SumValue CurMd5
= List
.Description_md5();
277 std::string CurLang
= List
.DescriptionLanguage();
279 for (Ver
= Pkg
.VersionList(); Ver
.end() == false; ++Ver
)
281 pkgCache::DescIterator Desc
= Ver
.DescriptionList();
282 Dynamic
<pkgCache::DescIterator
> DynDesc(Desc
);
283 map_ptrloc
*LastDesc
= &Ver
->DescriptionList
;
285 // don't add a new description if we have one for the given
287 if (IsDuplicateDescription(Desc
, CurMd5
, CurLang
) == true)
290 for (Desc
= Ver
.DescriptionList();
292 LastDesc
= &Desc
->NextDesc
, ++Desc
)
294 if (MD5SumValue(Desc
.md5()) != CurMd5
)
297 // Add new description
298 void const * const oldMap
= Map
.Data();
299 map_ptrloc
const descindex
= NewDescription(Desc
, CurLang
, CurMd5
, *LastDesc
);
300 if (oldMap
!= Map
.Data())
301 LastDesc
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
302 *LastDesc
= descindex
;
303 Desc
->ParentPkg
= Pkg
.Index();
305 if ((*LastDesc
== 0 && _error
->PendingError()) || NewFileDesc(Desc
,List
) == false)
306 return _error
->Error(_("Error occurred while processing %s (NewFileDesc1)"), Pkg
.Name());
314 // CacheGenerator::MergeListVersion /*{{{*/
315 bool pkgCacheGenerator::MergeListVersion(ListParser
&List
, pkgCache::PkgIterator
&Pkg
,
316 std::string
const &Version
, pkgCache::VerIterator
* &OutVer
)
318 pkgCache::VerIterator Ver
= Pkg
.VersionList();
319 Dynamic
<pkgCache::VerIterator
> DynVer(Ver
);
320 map_ptrloc
*LastVer
= &Pkg
->VersionList
;
321 void const * oldMap
= Map
.Data();
323 unsigned long const Hash
= List
.VersionHash();
324 if (Ver
.end() == false)
326 /* We know the list is sorted so we use that fact in the search.
327 Insertion of new versions is done with correct sorting */
329 for (; Ver
.end() == false; LastVer
= &Ver
->NextVer
, Ver
++)
331 Res
= Cache
.VS
->CmpVersion(Version
,Ver
.VerStr());
332 // Version is higher as current version - insert here
335 // Versionstrings are equal - is hash also equal?
336 if (Res
== 0 && Ver
->Hash
== Hash
)
338 // proceed with the next till we have either the right
339 // or we found another version (which will be lower)
342 /* We already have a version for this item, record that we saw it */
343 if (Res
== 0 && Ver
.end() == false && Ver
->Hash
== Hash
)
345 if (List
.UsePackage(Pkg
,Ver
) == false)
346 return _error
->Error(_("Error occurred while processing %s (UsePackage2)"),
349 if (NewFileVer(Ver
,List
) == false)
350 return _error
->Error(_("Error occurred while processing %s (NewFileVer1)"),
353 // Read only a single record and return
365 map_ptrloc
const verindex
= NewVersion(Ver
,Version
,*LastVer
);
366 if (verindex
== 0 && _error
->PendingError())
367 return _error
->Error(_("Error occurred while processing %s (NewVersion%d)"),
370 if (oldMap
!= Map
.Data())
371 LastVer
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
373 Ver
->ParentPkg
= Pkg
.Index();
376 if (List
.NewVersion(Ver
) == false)
377 return _error
->Error(_("Error occurred while processing %s (NewVersion%d)"),
380 if (List
.UsePackage(Pkg
,Ver
) == false)
381 return _error
->Error(_("Error occurred while processing %s (UsePackage3)"),
384 if (NewFileVer(Ver
,List
) == false)
385 return _error
->Error(_("Error occurred while processing %s (NewVersion%d)"),
388 // Read only a single record and return
395 /* Record the Description (it is not translated) */
396 MD5SumValue CurMd5
= List
.Description_md5();
397 if (CurMd5
.Value().empty() == true)
399 std::string CurLang
= List
.DescriptionLanguage();
401 /* Before we add a new description we first search in the group for
402 a version with a description of the same MD5 - if so we reuse this
403 description group instead of creating our own for this version */
404 pkgCache::GrpIterator Grp
= Pkg
.Group();
405 for (pkgCache::PkgIterator P
= Grp
.PackageList();
406 P
.end() == false; P
= Grp
.NextPkg(P
))
408 for (pkgCache::VerIterator V
= P
.VersionList();
409 V
.end() == false; ++V
)
411 if (IsDuplicateDescription(V
.DescriptionList(), CurMd5
, "") == false)
413 Ver
->DescriptionList
= V
->DescriptionList
;
418 // We haven't found reusable descriptions, so add the first description
419 pkgCache::DescIterator Desc
= Ver
.DescriptionList();
420 Dynamic
<pkgCache::DescIterator
> DynDesc(Desc
);
421 map_ptrloc
*LastDesc
= &Ver
->DescriptionList
;
424 map_ptrloc
const descindex
= NewDescription(Desc
, List
.DescriptionLanguage(), List
.Description_md5(), *LastDesc
);
425 if (oldMap
!= Map
.Data())
426 LastDesc
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
427 *LastDesc
= descindex
;
428 Desc
->ParentPkg
= Pkg
.Index();
430 if ((*LastDesc
== 0 && _error
->PendingError()) || NewFileDesc(Desc
,List
) == false)
431 return _error
->Error(_("Error occurred while processing %s (NewFileDesc2)"),Pkg
.Name());
437 // CacheGenerator::MergeFileProvides - Merge file provides /*{{{*/
438 // ---------------------------------------------------------------------
439 /* If we found any file depends while parsing the main list we need to
440 resolve them. Since it is undesired to load the entire list of files
441 into the cache as virtual packages we do a two stage effort. MergeList
442 identifies the file depends and this creates Provdies for them by
443 re-parsing all the indexs. */
444 bool pkgCacheGenerator::MergeFileProvides(ListParser
&List
)
448 unsigned int Counter
= 0;
449 while (List
.Step() == true)
451 string PackageName
= List
.Package();
452 if (PackageName
.empty() == true)
454 string Version
= List
.Version();
455 if (Version
.empty() == true)
458 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(PackageName
);
459 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
460 if (Pkg
.end() == true)
461 return _error
->Error(_("Error occurred while processing %s (FindPkg)"),
462 PackageName
.c_str());
464 if (Counter
% 100 == 0 && Progress
!= 0)
465 Progress
->Progress(List
.Offset());
467 unsigned long Hash
= List
.VersionHash();
468 pkgCache::VerIterator Ver
= Pkg
.VersionList();
469 Dynamic
<pkgCache::VerIterator
> DynVer(Ver
);
470 for (; Ver
.end() == false; ++Ver
)
472 if (Ver
->Hash
== Hash
&& Version
.c_str() == Ver
.VerStr())
474 if (List
.CollectFileProvides(Cache
,Ver
) == false)
475 return _error
->Error(_("Error occurred while processing %s (CollectFileProvides)"),PackageName
.c_str());
480 if (Ver
.end() == true)
481 _error
->Warning(_("Package %s %s was not found while processing file dependencies"),PackageName
.c_str(),Version
.c_str());
487 // CacheGenerator::NewGroup - Add a new group /*{{{*/
488 // ---------------------------------------------------------------------
489 /* This creates a new group structure and adds it to the hash table */
490 bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator
&Grp
, const string
&Name
)
492 Grp
= Cache
.FindGrp(Name
);
493 if (Grp
.end() == false)
497 map_ptrloc
const Group
= AllocateInMap(sizeof(pkgCache::Group
));
498 if (unlikely(Group
== 0))
501 Grp
= pkgCache::GrpIterator(Cache
, Cache
.GrpP
+ Group
);
502 map_ptrloc
const idxName
= WriteStringInMap(Name
);
503 if (unlikely(idxName
== 0))
507 // Insert it into the hash table
508 unsigned long const Hash
= Cache
.Hash(Name
);
509 Grp
->Next
= Cache
.HeaderP
->GrpHashTable
[Hash
];
510 Cache
.HeaderP
->GrpHashTable
[Hash
] = Group
;
512 Grp
->ID
= Cache
.HeaderP
->GroupCount
++;
516 // CacheGenerator::NewPackage - Add a new package /*{{{*/
517 // ---------------------------------------------------------------------
518 /* This creates a new package structure and adds it to the hash table */
519 bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator
&Pkg
,const string
&Name
,
520 const string
&Arch
) {
521 pkgCache::GrpIterator Grp
;
522 Dynamic
<pkgCache::GrpIterator
> DynGrp(Grp
);
523 if (unlikely(NewGroup(Grp
, Name
) == false))
526 Pkg
= Grp
.FindPkg(Arch
);
527 if (Pkg
.end() == false)
531 map_ptrloc
const Package
= AllocateInMap(sizeof(pkgCache::Package
));
532 if (unlikely(Package
== 0))
534 Pkg
= pkgCache::PkgIterator(Cache
,Cache
.PkgP
+ Package
);
536 // Insert the package into our package list
537 if (Grp
->FirstPackage
== 0) // the group is new
539 // Insert it into the hash table
540 unsigned long const Hash
= Cache
.Hash(Name
);
541 Pkg
->NextPackage
= Cache
.HeaderP
->PkgHashTable
[Hash
];
542 Cache
.HeaderP
->PkgHashTable
[Hash
] = Package
;
543 Grp
->FirstPackage
= Package
;
545 else // Group the Packages together
547 // this package is the new last package
548 pkgCache::PkgIterator
LastPkg(Cache
, Cache
.PkgP
+ Grp
->LastPackage
);
549 Pkg
->NextPackage
= LastPkg
->NextPackage
;
550 LastPkg
->NextPackage
= Package
;
552 Grp
->LastPackage
= Package
;
554 // Set the name, arch and the ID
555 Pkg
->Name
= Grp
->Name
;
556 Pkg
->Group
= Grp
.Index();
557 // all is mapped to the native architecture
558 map_ptrloc
const idxArch
= (Arch
== "all") ? Cache
.HeaderP
->Architecture
: WriteUniqString(Arch
.c_str());
559 if (unlikely(idxArch
== 0))
562 Pkg
->ID
= Cache
.HeaderP
->PackageCount
++;
567 // CacheGenerator::NewFileVer - Create a new File<->Version association /*{{{*/
568 // ---------------------------------------------------------------------
570 bool pkgCacheGenerator::NewFileVer(pkgCache::VerIterator
&Ver
,
573 if (CurrentFile
== 0)
577 map_ptrloc
const VerFile
= AllocateInMap(sizeof(pkgCache::VerFile
));
581 pkgCache::VerFileIterator
VF(Cache
,Cache
.VerFileP
+ VerFile
);
582 VF
->File
= CurrentFile
- Cache
.PkgFileP
;
584 // Link it to the end of the list
585 map_ptrloc
*Last
= &Ver
->FileList
;
586 for (pkgCache::VerFileIterator V
= Ver
.FileList(); V
.end() == false; ++V
)
588 VF
->NextFile
= *Last
;
591 VF
->Offset
= List
.Offset();
592 VF
->Size
= List
.Size();
593 if (Cache
.HeaderP
->MaxVerFileSize
< VF
->Size
)
594 Cache
.HeaderP
->MaxVerFileSize
= VF
->Size
;
595 Cache
.HeaderP
->VerFileCount
++;
600 // CacheGenerator::NewVersion - Create a new Version /*{{{*/
601 // ---------------------------------------------------------------------
602 /* This puts a version structure in the linked list */
603 unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator
&Ver
,
604 const string
&VerStr
,
608 map_ptrloc
const Version
= AllocateInMap(sizeof(pkgCache::Version
));
613 Ver
= pkgCache::VerIterator(Cache
,Cache
.VerP
+ Version
);
615 Ver
->ID
= Cache
.HeaderP
->VersionCount
++;
616 map_ptrloc
const idxVerStr
= WriteStringInMap(VerStr
);
617 if (unlikely(idxVerStr
== 0))
619 Ver
->VerStr
= idxVerStr
;
624 // CacheGenerator::NewFileDesc - Create a new File<->Desc association /*{{{*/
625 // ---------------------------------------------------------------------
627 bool pkgCacheGenerator::NewFileDesc(pkgCache::DescIterator
&Desc
,
630 if (CurrentFile
== 0)
634 map_ptrloc
const DescFile
= AllocateInMap(sizeof(pkgCache::DescFile
));
638 pkgCache::DescFileIterator
DF(Cache
,Cache
.DescFileP
+ DescFile
);
639 DF
->File
= CurrentFile
- Cache
.PkgFileP
;
641 // Link it to the end of the list
642 map_ptrloc
*Last
= &Desc
->FileList
;
643 for (pkgCache::DescFileIterator D
= Desc
.FileList(); D
.end() == false; ++D
)
646 DF
->NextFile
= *Last
;
649 DF
->Offset
= List
.Offset();
650 DF
->Size
= List
.Size();
651 if (Cache
.HeaderP
->MaxDescFileSize
< DF
->Size
)
652 Cache
.HeaderP
->MaxDescFileSize
= DF
->Size
;
653 Cache
.HeaderP
->DescFileCount
++;
658 // CacheGenerator::NewDescription - Create a new Description /*{{{*/
659 // ---------------------------------------------------------------------
660 /* This puts a description structure in the linked list */
661 map_ptrloc
pkgCacheGenerator::NewDescription(pkgCache::DescIterator
&Desc
,
663 const MD5SumValue
&md5sum
,
667 map_ptrloc
const Description
= AllocateInMap(sizeof(pkgCache::Description
));
668 if (Description
== 0)
672 Desc
= pkgCache::DescIterator(Cache
,Cache
.DescP
+ Description
);
673 Desc
->NextDesc
= Next
;
674 Desc
->ID
= Cache
.HeaderP
->DescriptionCount
++;
675 map_ptrloc
const idxlanguage_code
= WriteStringInMap(Lang
);
676 map_ptrloc
const idxmd5sum
= WriteStringInMap(md5sum
.Value());
677 if (unlikely(idxlanguage_code
== 0 || idxmd5sum
== 0))
679 Desc
->language_code
= idxlanguage_code
;
680 Desc
->md5sum
= idxmd5sum
;
685 // CacheGenerator::FinishCache - do various finish operations /*{{{*/
686 // ---------------------------------------------------------------------
687 /* This prepares the Cache for delivery */
688 bool pkgCacheGenerator::FinishCache(OpProgress
*Progress
)
690 // FIXME: add progress reporting for this operation
691 // Do we have different architectures in your groups ?
692 vector
<string
> archs
= APT::Configuration::getArchitectures();
693 if (archs
.size() > 1)
695 // Create Conflicts in between the group
696 pkgCache::GrpIterator G
= GetCache().GrpBegin();
697 Dynamic
<pkgCache::GrpIterator
> DynG(G
);
698 for (; G
.end() != true; ++G
)
700 string
const PkgName
= G
.Name();
701 pkgCache::PkgIterator P
= G
.PackageList();
702 Dynamic
<pkgCache::PkgIterator
> DynP(P
);
703 for (; P
.end() != true; P
= G
.NextPkg(P
))
705 pkgCache::PkgIterator allPkg
;
706 Dynamic
<pkgCache::PkgIterator
> DynallPkg(allPkg
);
707 pkgCache::VerIterator V
= P
.VersionList();
708 Dynamic
<pkgCache::VerIterator
> DynV(V
);
709 for (; V
.end() != true; ++V
)
711 // copy P.Arch() into a string here as a cache remap
712 // in NewDepends() later may alter the pointer location
713 string Arch
= P
.Arch() == NULL
? "" : P
.Arch();
714 map_ptrloc
*OldDepLast
= NULL
;
715 /* MultiArch handling introduces a lot of implicit Dependencies:
716 - MultiArch: same → Co-Installable if they have the same version
717 - Architecture: all → Need to be Co-Installable for internal reasons
718 - All others conflict with all other group members */
719 bool const coInstall
= ((V
->MultiArch
& pkgCache::Version::Same
) == pkgCache::Version::Same
);
720 for (vector
<string
>::const_iterator A
= archs
.begin(); A
!= archs
.end(); ++A
)
724 /* We allow only one installed arch at the time
725 per group, therefore each group member conflicts
726 with all other group members */
727 pkgCache::PkgIterator D
= G
.FindPkg(*A
);
728 Dynamic
<pkgCache::PkgIterator
> DynD(D
);
731 if (coInstall
== true)
733 // Replaces: ${self}:other ( << ${binary:Version})
734 NewDepends(D
, V
, V
.VerStr(),
735 pkgCache::Dep::Less
, pkgCache::Dep::Replaces
,
737 // Breaks: ${self}:other (!= ${binary:Version})
738 NewDepends(D
, V
, V
.VerStr(),
739 pkgCache::Dep::NotEquals
, pkgCache::Dep::DpkgBreaks
,
742 // Conflicts: ${self}:other
744 pkgCache::Dep::NoOp
, pkgCache::Dep::Conflicts
,
755 // CacheGenerator::NewDepends - Create a dependency element /*{{{*/
756 // ---------------------------------------------------------------------
757 /* This creates a dependency element in the tree. It is linked to the
758 version and to the package that it is pointing to. */
759 bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator
&Pkg
,
760 pkgCache::VerIterator
&Ver
,
761 string
const &Version
,
762 unsigned int const &Op
,
763 unsigned int const &Type
,
764 map_ptrloc
* &OldDepLast
)
766 void const * const oldMap
= Map
.Data();
768 map_ptrloc
const Dependency
= AllocateInMap(sizeof(pkgCache::Dependency
));
769 if (unlikely(Dependency
== 0))
773 pkgCache::DepIterator
Dep(Cache
,Cache
.DepP
+ Dependency
);
774 Dynamic
<pkgCache::DepIterator
> DynDep(Dep
);
775 Dep
->ParentVer
= Ver
.Index();
778 Dep
->ID
= Cache
.HeaderP
->DependsCount
++;
780 // Probe the reverse dependency list for a version string that matches
781 if (Version
.empty() == false)
783 /* for (pkgCache::DepIterator I = Pkg.RevDependsList(); I.end() == false; I++)
784 if (I->Version != 0 && I.TargetVer() == Version)
785 Dep->Version = I->Version;*/
786 if (Dep
->Version
== 0) {
787 map_ptrloc
const index
= WriteStringInMap(Version
);
788 if (unlikely(index
== 0))
790 Dep
->Version
= index
;
794 // Link it to the package
795 Dep
->Package
= Pkg
.Index();
796 Dep
->NextRevDepends
= Pkg
->RevDepends
;
797 Pkg
->RevDepends
= Dep
.Index();
799 // Do we know where to link the Dependency to?
800 if (OldDepLast
== NULL
)
802 OldDepLast
= &Ver
->DependsList
;
803 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
804 OldDepLast
= &D
->NextDepends
;
805 } else if (oldMap
!= Map
.Data())
806 OldDepLast
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
808 Dep
->NextDepends
= *OldDepLast
;
809 *OldDepLast
= Dep
.Index();
810 OldDepLast
= &Dep
->NextDepends
;
815 // ListParser::NewDepends - Create the environment for a new dependency /*{{{*/
816 // ---------------------------------------------------------------------
817 /* This creates a Group and the Package to link this dependency to if
818 needed and handles also the caching of the old endpoint */
819 bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator
&Ver
,
820 const string
&PackageName
,
822 const string
&Version
,
826 pkgCache::GrpIterator Grp
;
827 Dynamic
<pkgCache::GrpIterator
> DynGrp(Grp
);
828 if (unlikely(Owner
->NewGroup(Grp
, PackageName
) == false))
831 // Locate the target package
832 pkgCache::PkgIterator Pkg
= Grp
.FindPkg(Arch
);
833 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
834 if (Pkg
.end() == true) {
835 if (unlikely(Owner
->NewPackage(Pkg
, PackageName
, Arch
) == false))
839 // Is it a file dependency?
840 if (unlikely(PackageName
[0] == '/'))
841 FoundFileDeps
= true;
843 /* Caching the old end point speeds up generation substantially */
844 if (OldDepVer
!= Ver
) {
849 return Owner
->NewDepends(Pkg
, Ver
, Version
, Op
, Type
, OldDepLast
);
852 // ListParser::NewProvides - Create a Provides element /*{{{*/
853 // ---------------------------------------------------------------------
855 bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator
&Ver
,
856 const string
&PkgName
,
857 const string
&PkgArch
,
858 const string
&Version
)
860 pkgCache
&Cache
= Owner
->Cache
;
862 // We do not add self referencing provides
863 if (Ver
.ParentPkg().Name() == PkgName
&& (PkgArch
== Ver
.ParentPkg().Arch() ||
864 (PkgArch
== "all" && strcmp((Cache
.StrP
+ Cache
.HeaderP
->Architecture
), Ver
.ParentPkg().Arch()) == 0)))
868 map_ptrloc
const Provides
= Owner
->AllocateInMap(sizeof(pkgCache::Provides
));
869 if (unlikely(Provides
== 0))
871 Cache
.HeaderP
->ProvidesCount
++;
874 pkgCache::PrvIterator
Prv(Cache
,Cache
.ProvideP
+ Provides
,Cache
.PkgP
);
875 Dynamic
<pkgCache::PrvIterator
> DynPrv(Prv
);
876 Prv
->Version
= Ver
.Index();
877 Prv
->NextPkgProv
= Ver
->ProvidesList
;
878 Ver
->ProvidesList
= Prv
.Index();
879 if (Version
.empty() == false && unlikely((Prv
->ProvideVersion
= WriteString(Version
)) == 0))
882 // Locate the target package
883 pkgCache::PkgIterator Pkg
;
884 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
885 if (unlikely(Owner
->NewPackage(Pkg
,PkgName
, PkgArch
) == false))
888 // Link it to the package
889 Prv
->ParentPkg
= Pkg
.Index();
890 Prv
->NextProvides
= Pkg
->ProvidesList
;
891 Pkg
->ProvidesList
= Prv
.Index();
896 // CacheGenerator::SelectFile - Select the current file being parsed /*{{{*/
897 // ---------------------------------------------------------------------
898 /* This is used to select which file is to be associated with all newly
899 added versions. The caller is responsible for setting the IMS fields. */
900 bool pkgCacheGenerator::SelectFile(const string
&File
,const string
&Site
,
901 const pkgIndexFile
&Index
,
904 // Get some space for the structure
905 map_ptrloc
const idxFile
= AllocateInMap(sizeof(*CurrentFile
));
906 if (unlikely(idxFile
== 0))
908 CurrentFile
= Cache
.PkgFileP
+ idxFile
;
911 map_ptrloc
const idxFileName
= WriteStringInMap(File
);
912 map_ptrloc
const idxSite
= WriteUniqString(Site
);
913 if (unlikely(idxFileName
== 0 || idxSite
== 0))
915 CurrentFile
->FileName
= idxFileName
;
916 CurrentFile
->Site
= idxSite
;
917 CurrentFile
->NextFile
= Cache
.HeaderP
->FileList
;
918 CurrentFile
->Flags
= Flags
;
919 CurrentFile
->ID
= Cache
.HeaderP
->PackageFileCount
;
920 map_ptrloc
const idxIndexType
= WriteUniqString(Index
.GetType()->Label
);
921 if (unlikely(idxIndexType
== 0))
923 CurrentFile
->IndexType
= idxIndexType
;
925 Cache
.HeaderP
->FileList
= CurrentFile
- Cache
.PkgFileP
;
926 Cache
.HeaderP
->PackageFileCount
++;
929 Progress
->SubProgress(Index
.Size());
933 // CacheGenerator::WriteUniqueString - Insert a unique string /*{{{*/
934 // ---------------------------------------------------------------------
935 /* This is used to create handles to strings. Given the same text it
936 always returns the same number */
937 unsigned long pkgCacheGenerator::WriteUniqString(const char *S
,
940 /* We use a very small transient hash table here, this speeds up generation
941 by a fair amount on slower machines */
942 pkgCache::StringItem
*&Bucket
= UniqHash
[(S
[0]*5 + S
[1]) % _count(UniqHash
)];
944 stringcmp(S
,S
+Size
,Cache
.StrP
+ Bucket
->String
) == 0)
945 return Bucket
->String
;
947 // Search for an insertion point
948 pkgCache::StringItem
*I
= Cache
.StringItemP
+ Cache
.HeaderP
->StringList
;
950 map_ptrloc
*Last
= &Cache
.HeaderP
->StringList
;
951 for (; I
!= Cache
.StringItemP
; Last
= &I
->NextItem
,
952 I
= Cache
.StringItemP
+ I
->NextItem
)
954 Res
= stringcmp(S
,S
+Size
,Cache
.StrP
+ I
->String
);
967 void const * const oldMap
= Map
.Data();
968 map_ptrloc
const Item
= AllocateInMap(sizeof(pkgCache::StringItem
));
972 map_ptrloc
const idxString
= WriteStringInMap(S
,Size
);
973 if (unlikely(idxString
== 0))
975 if (oldMap
!= Map
.Data()) {
976 Last
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
977 I
+= (pkgCache::StringItem
*) Map
.Data() - (pkgCache::StringItem
*) oldMap
;
981 // Fill in the structure
982 pkgCache::StringItem
*ItemP
= Cache
.StringItemP
+ Item
;
983 ItemP
->NextItem
= I
- Cache
.StringItemP
;
984 ItemP
->String
= idxString
;
987 return ItemP
->String
;
990 // CheckValidity - Check that a cache is up-to-date /*{{{*/
991 // ---------------------------------------------------------------------
992 /* This just verifies that each file in the list of index files exists,
993 has matching attributes with the cache and the cache does not have
995 static bool CheckValidity(const string
&CacheFile
,
1001 bool const Debug
= _config
->FindB("Debug::pkgCacheGen", false);
1002 // No file, certainly invalid
1003 if (CacheFile
.empty() == true || FileExists(CacheFile
) == false)
1006 std::clog
<< "CacheFile doesn't exist" << std::endl
;
1010 if (List
.GetLastModifiedTime() > GetModificationTime(CacheFile
))
1013 std::clog
<< "sources.list is newer than the cache" << std::endl
;
1018 FileFd
CacheF(CacheFile
,FileFd::ReadOnly
);
1019 SPtr
<MMap
> Map
= new MMap(CacheF
,0);
1020 pkgCache
Cache(Map
);
1021 if (_error
->PendingError() == true || Map
->Size() == 0)
1024 std::clog
<< "Errors are pending or Map is empty()" << std::endl
;
1029 /* Now we check every index file, see if it is in the cache,
1030 verify the IMS data and check that it is on the disk too.. */
1031 SPtrArray
<bool> Visited
= new bool[Cache
.HeaderP
->PackageFileCount
];
1032 memset(Visited
,0,sizeof(*Visited
)*Cache
.HeaderP
->PackageFileCount
);
1033 for (; Start
!= End
; ++Start
)
1036 std::clog
<< "Checking PkgFile " << (*Start
)->Describe() << ": ";
1037 if ((*Start
)->HasPackages() == false)
1040 std::clog
<< "Has NO packages" << std::endl
;
1044 if ((*Start
)->Exists() == false)
1046 #if 0 // mvo: we no longer give a message here (Default Sources spec)
1047 _error
->WarningE("stat",_("Couldn't stat source package list %s"),
1048 (*Start
)->Describe().c_str());
1051 std::clog
<< "file doesn't exist" << std::endl
;
1055 // FindInCache is also expected to do an IMS check.
1056 pkgCache::PkgFileIterator File
= (*Start
)->FindInCache(Cache
);
1057 if (File
.end() == true)
1060 std::clog
<< "FindInCache returned end-Pointer" << std::endl
;
1064 Visited
[File
->ID
] = true;
1066 std::clog
<< "with ID " << File
->ID
<< " is valid" << std::endl
;
1069 for (unsigned I
= 0; I
!= Cache
.HeaderP
->PackageFileCount
; I
++)
1070 if (Visited
[I
] == false)
1073 std::clog
<< "File with ID" << I
<< " wasn't visited" << std::endl
;
1077 if (_error
->PendingError() == true)
1081 std::clog
<< "Validity failed because of pending errors:" << std::endl
;
1082 _error
->DumpErrors();
1089 *OutMap
= Map
.UnGuard();
1093 // ComputeSize - Compute the total size of a bunch of files /*{{{*/
1094 // ---------------------------------------------------------------------
1095 /* Size is kind of an abstract notion that is only used for the progress
1097 static unsigned long ComputeSize(FileIterator Start
,FileIterator End
)
1099 unsigned long TotalSize
= 0;
1100 for (; Start
!= End
; ++Start
)
1102 if ((*Start
)->HasPackages() == false)
1104 TotalSize
+= (*Start
)->Size();
1109 // BuildCache - Merge the list of index files into the cache /*{{{*/
1110 // ---------------------------------------------------------------------
1112 static bool BuildCache(pkgCacheGenerator
&Gen
,
1113 OpProgress
*Progress
,
1114 unsigned long &CurrentSize
,unsigned long TotalSize
,
1115 FileIterator Start
, FileIterator End
)
1118 for (I
= Start
; I
!= End
; ++I
)
1120 if ((*I
)->HasPackages() == false)
1123 if ((*I
)->Exists() == false)
1126 if ((*I
)->FindInCache(Gen
.GetCache()).end() == false)
1128 _error
->Warning("Duplicate sources.list entry %s",
1129 (*I
)->Describe().c_str());
1133 unsigned long Size
= (*I
)->Size();
1134 if (Progress
!= NULL
)
1135 Progress
->OverallProgress(CurrentSize
,TotalSize
,Size
,_("Reading package lists"));
1136 CurrentSize
+= Size
;
1138 if ((*I
)->Merge(Gen
,Progress
) == false)
1142 if (Gen
.HasFileDeps() == true)
1144 if (Progress
!= NULL
)
1146 TotalSize
= ComputeSize(Start
, End
);
1148 for (I
= Start
; I
!= End
; ++I
)
1150 unsigned long Size
= (*I
)->Size();
1151 if (Progress
!= NULL
)
1152 Progress
->OverallProgress(CurrentSize
,TotalSize
,Size
,_("Collecting File Provides"));
1153 CurrentSize
+= Size
;
1154 if ((*I
)->MergeFileProvides(Gen
,Progress
) == false)
1162 // CacheGenerator::CreateDynamicMMap - load an mmap with configuration options /*{{{*/
1163 DynamicMMap
* pkgCacheGenerator::CreateDynamicMMap(FileFd
*CacheF
, unsigned long Flags
) {
1164 unsigned long const MapStart
= _config
->FindI("APT::Cache-Start", 24*1024*1024);
1165 unsigned long const MapGrow
= _config
->FindI("APT::Cache-Grow", 1*1024*1024);
1166 unsigned long const MapLimit
= _config
->FindI("APT::Cache-Limit", 0);
1167 Flags
|= MMap::Moveable
;
1168 if (_config
->FindB("APT::Cache-Fallback", false) == true)
1169 Flags
|= MMap::Fallback
;
1171 return new DynamicMMap(*CacheF
, Flags
, MapStart
, MapGrow
, MapLimit
);
1173 return new DynamicMMap(Flags
, MapStart
, MapGrow
, MapLimit
);
1176 // CacheGenerator::MakeStatusCache - Construct the status cache /*{{{*/
1177 // ---------------------------------------------------------------------
1178 /* This makes sure that the status cache (the cache that has all
1179 index files from the sources list and all local ones) is ready
1180 to be mmaped. If OutMap is not zero then a MMap object representing
1181 the cache will be stored there. This is pretty much mandetory if you
1182 are using AllowMem. AllowMem lets the function be run as non-root
1183 where it builds the cache 'fast' into a memory buffer. */
1184 __deprecated
bool pkgMakeStatusCache(pkgSourceList
&List
,OpProgress
&Progress
,
1185 MMap
**OutMap
, bool AllowMem
)
1186 { return pkgCacheGenerator::MakeStatusCache(List
, &Progress
, OutMap
, AllowMem
); }
1187 bool pkgCacheGenerator::MakeStatusCache(pkgSourceList
&List
,OpProgress
*Progress
,
1188 MMap
**OutMap
,bool AllowMem
)
1190 bool const Debug
= _config
->FindB("Debug::pkgCacheGen", false);
1192 vector
<pkgIndexFile
*> Files
;
1193 for (vector
<metaIndex
*>::const_iterator i
= List
.begin();
1197 vector
<pkgIndexFile
*> *Indexes
= (*i
)->GetIndexFiles();
1198 for (vector
<pkgIndexFile
*>::const_iterator j
= Indexes
->begin();
1199 j
!= Indexes
->end();
1201 Files
.push_back (*j
);
1204 unsigned long const EndOfSource
= Files
.size();
1205 if (_system
->AddStatusFiles(Files
) == false)
1208 // Decide if we can write to the files..
1209 string
const CacheFile
= _config
->FindFile("Dir::Cache::pkgcache");
1210 string
const SrcCacheFile
= _config
->FindFile("Dir::Cache::srcpkgcache");
1212 // ensure the cache directory exists
1213 if (CacheFile
.empty() == false || SrcCacheFile
.empty() == false)
1215 string dir
= _config
->FindDir("Dir::Cache");
1216 size_t const len
= dir
.size();
1217 if (len
> 5 && dir
.find("/apt/", len
- 6, 5) == len
- 5)
1218 dir
= dir
.substr(0, len
- 5);
1219 if (CacheFile
.empty() == false)
1220 CreateDirectory(dir
, flNotFile(CacheFile
));
1221 if (SrcCacheFile
.empty() == false)
1222 CreateDirectory(dir
, flNotFile(SrcCacheFile
));
1225 // Decide if we can write to the cache
1226 bool Writeable
= false;
1227 if (CacheFile
.empty() == false)
1228 Writeable
= access(flNotFile(CacheFile
).c_str(),W_OK
) == 0;
1230 if (SrcCacheFile
.empty() == false)
1231 Writeable
= access(flNotFile(SrcCacheFile
).c_str(),W_OK
) == 0;
1233 std::clog
<< "Do we have write-access to the cache files? " << (Writeable
? "YES" : "NO") << std::endl
;
1235 if (Writeable
== false && AllowMem
== false && CacheFile
.empty() == false)
1236 return _error
->Error(_("Unable to write to %s"),flNotFile(CacheFile
).c_str());
1238 if (Progress
!= NULL
)
1239 Progress
->OverallProgress(0,1,1,_("Reading package lists"));
1241 // Cache is OK, Fin.
1242 if (CheckValidity(CacheFile
, List
, Files
.begin(),Files
.end(),OutMap
) == true)
1244 if (Progress
!= NULL
)
1245 Progress
->OverallProgress(1,1,1,_("Reading package lists"));
1247 std::clog
<< "pkgcache.bin is valid - no need to build anything" << std::endl
;
1250 else if (Debug
== true)
1251 std::clog
<< "pkgcache.bin is NOT valid" << std::endl
;
1253 /* At this point we know we need to reconstruct the package cache,
1255 SPtr
<FileFd
> CacheF
;
1256 SPtr
<DynamicMMap
> Map
;
1257 if (Writeable
== true && CacheFile
.empty() == false)
1259 _error
->PushToStack();
1260 unlink(CacheFile
.c_str());
1261 CacheF
= new FileFd(CacheFile
,FileFd::WriteAtomic
);
1262 fchmod(CacheF
->Fd(),0644);
1263 Map
= CreateDynamicMMap(CacheF
, MMap::Public
);
1264 if (_error
->PendingError() == true)
1266 delete CacheF
.UnGuard();
1267 delete Map
.UnGuard();
1269 std::clog
<< "Open filebased MMap FAILED" << std::endl
;
1271 if (AllowMem
== false)
1273 _error
->MergeWithStack();
1276 _error
->RevertToStack();
1278 else if (Debug
== true)
1280 _error
->MergeWithStack();
1281 std::clog
<< "Open filebased MMap" << std::endl
;
1284 if (Writeable
== false || CacheFile
.empty() == true)
1286 // Just build it in memory..
1287 Map
= CreateDynamicMMap(NULL
);
1289 std::clog
<< "Open memory Map (not filebased)" << std::endl
;
1292 // Lets try the source cache.
1293 unsigned long CurrentSize
= 0;
1294 unsigned long TotalSize
= 0;
1295 if (CheckValidity(SrcCacheFile
, List
, Files
.begin(),
1296 Files
.begin()+EndOfSource
) == true)
1299 std::clog
<< "srcpkgcache.bin is valid - populate MMap with it." << std::endl
;
1300 // Preload the map with the source cache
1301 FileFd
SCacheF(SrcCacheFile
,FileFd::ReadOnly
);
1302 unsigned long const alloc
= Map
->RawAllocate(SCacheF
.Size());
1303 if ((alloc
== 0 && _error
->PendingError())
1304 || SCacheF
.Read((unsigned char *)Map
->Data() + alloc
,
1305 SCacheF
.Size()) == false)
1308 TotalSize
= ComputeSize(Files
.begin()+EndOfSource
,Files
.end());
1310 // Build the status cache
1311 pkgCacheGenerator
Gen(Map
.Get(),Progress
);
1312 if (_error
->PendingError() == true)
1314 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1315 Files
.begin()+EndOfSource
,Files
.end()) == false)
1318 // FIXME: move me to a better place
1319 Gen
.FinishCache(Progress
);
1324 std::clog
<< "srcpkgcache.bin is NOT valid - rebuild" << std::endl
;
1325 TotalSize
= ComputeSize(Files
.begin(),Files
.end());
1327 // Build the source cache
1328 pkgCacheGenerator
Gen(Map
.Get(),Progress
);
1329 if (_error
->PendingError() == true)
1331 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1332 Files
.begin(),Files
.begin()+EndOfSource
) == false)
1336 if (Writeable
== true && SrcCacheFile
.empty() == false)
1338 FileFd
SCacheF(SrcCacheFile
,FileFd::WriteAtomic
);
1339 if (_error
->PendingError() == true)
1342 fchmod(SCacheF
.Fd(),0644);
1344 // Write out the main data
1345 if (SCacheF
.Write(Map
->Data(),Map
->Size()) == false)
1346 return _error
->Error(_("IO Error saving source cache"));
1349 // Write out the proper header
1350 Gen
.GetCache().HeaderP
->Dirty
= false;
1351 if (SCacheF
.Seek(0) == false ||
1352 SCacheF
.Write(Map
->Data(),sizeof(*Gen
.GetCache().HeaderP
)) == false)
1353 return _error
->Error(_("IO Error saving source cache"));
1354 Gen
.GetCache().HeaderP
->Dirty
= true;
1358 // Build the status cache
1359 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1360 Files
.begin()+EndOfSource
,Files
.end()) == false)
1363 // FIXME: move me to a better place
1364 Gen
.FinishCache(Progress
);
1367 std::clog
<< "Caches are ready for shipping" << std::endl
;
1369 if (_error
->PendingError() == true)
1375 delete Map
.UnGuard();
1376 *OutMap
= new MMap(*CacheF
,0);
1380 *OutMap
= Map
.UnGuard();
1387 // CacheGenerator::MakeOnlyStatusCache - Build only a status files cache/*{{{*/
1388 // ---------------------------------------------------------------------
1390 __deprecated
bool pkgMakeOnlyStatusCache(OpProgress
&Progress
,DynamicMMap
**OutMap
)
1391 { return pkgCacheGenerator::MakeOnlyStatusCache(&Progress
, OutMap
); }
1392 bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress
*Progress
,DynamicMMap
**OutMap
)
1394 vector
<pkgIndexFile
*> Files
;
1395 unsigned long EndOfSource
= Files
.size();
1396 if (_system
->AddStatusFiles(Files
) == false)
1399 SPtr
<DynamicMMap
> Map
= CreateDynamicMMap(NULL
);
1400 unsigned long CurrentSize
= 0;
1401 unsigned long TotalSize
= 0;
1403 TotalSize
= ComputeSize(Files
.begin()+EndOfSource
,Files
.end());
1405 // Build the status cache
1406 if (Progress
!= NULL
)
1407 Progress
->OverallProgress(0,1,1,_("Reading package lists"));
1408 pkgCacheGenerator
Gen(Map
.Get(),Progress
);
1409 if (_error
->PendingError() == true)
1411 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1412 Files
.begin()+EndOfSource
,Files
.end()) == false)
1415 // FIXME: move me to a better place
1416 Gen
.FinishCache(Progress
);
1418 if (_error
->PendingError() == true)
1420 *OutMap
= Map
.UnGuard();
1425 // IsDuplicateDescription /*{{{*/
1426 bool IsDuplicateDescription(pkgCache::DescIterator Desc
,
1427 MD5SumValue
const &CurMd5
, std::string
const &CurLang
)
1429 for ( ; Desc
.end() == false; ++Desc
)
1430 if (MD5SumValue(Desc
.md5()) == CurMd5
&& Desc
.LanguageCode() == CurLang
)