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/strutl.h>
22 #include <apt-pkg/sptr.h>
23 #include <apt-pkg/pkgsystem.h>
24 #include <apt-pkg/macros.h>
25 #include <apt-pkg/metaindex.h>
26 #include <apt-pkg/fileutl.h>
27 #include <apt-pkg/hashsum_template.h>
28 #include <apt-pkg/indexfile.h>
29 #include <apt-pkg/md5.h>
30 #include <apt-pkg/mmap.h>
31 #include <apt-pkg/pkgcache.h>
32 #include <apt-pkg/cacheiterators.h>
44 typedef std::vector
<pkgIndexFile
*>::iterator FileIterator
;
45 template <typename Iter
> std::vector
<Iter
*> pkgCacheGenerator::Dynamic
<Iter
>::toReMap
;
47 static bool IsDuplicateDescription(pkgCache::DescIterator Desc
,
48 MD5SumValue
const &CurMd5
, std::string
const &CurLang
);
52 // CacheGenerator::pkgCacheGenerator - Constructor /*{{{*/
53 // ---------------------------------------------------------------------
54 /* We set the dirty flag and make sure that is written to the disk */
55 pkgCacheGenerator::pkgCacheGenerator(DynamicMMap
*pMap
,OpProgress
*Prog
) :
56 Map(*pMap
), Cache(pMap
,false), Progress(Prog
),
60 memset(UniqHash
,0,sizeof(UniqHash
));
62 if (_error
->PendingError() == true)
67 // Setup the map interface..
68 Cache
.HeaderP
= (pkgCache::Header
*)Map
.Data();
69 if (Map
.RawAllocate(sizeof(pkgCache::Header
)) == 0 && _error
->PendingError() == true)
72 Map
.UsePools(*Cache
.HeaderP
->Pools
,sizeof(Cache
.HeaderP
->Pools
)/sizeof(Cache
.HeaderP
->Pools
[0]));
75 *Cache
.HeaderP
= pkgCache::Header();
77 // make room for the hashtables for packages and groups
78 if (Map
.RawAllocate(2 * (Cache
.HeaderP
->HashTableSize
* sizeof(map_pointer_t
))) == 0)
81 map_stringitem_t
const idxVerSysName
= WriteStringInMap(_system
->VS
->Label
);
82 if (unlikely(idxVerSysName
== 0))
84 Cache
.HeaderP
->VerSysName
= idxVerSysName
;
85 // this pointer is set in ReMap, but we need it now for WriteUniqString
86 Cache
.StringItemP
= (pkgCache::StringItem
*)Map
.Data();
87 map_stringitem_t
const idxArchitecture
= WriteUniqString(_config
->Find("APT::Architecture"));
88 if (unlikely(idxArchitecture
== 0))
90 Cache
.HeaderP
->Architecture
= idxArchitecture
;
92 std::vector
<std::string
> archs
= APT::Configuration::getArchitectures();
95 std::vector
<std::string
>::const_iterator a
= archs
.begin();
96 std::string list
= *a
;
97 for (++a
; a
!= archs
.end(); ++a
)
98 list
.append(",").append(*a
);
99 map_stringitem_t
const idxArchitectures
= WriteStringInMap(list
);
100 if (unlikely(idxArchitectures
== 0))
102 Cache
.HeaderP
->Architectures
= idxArchitectures
;
105 Cache
.HeaderP
->Architectures
= idxArchitecture
;
111 // Map directly from the existing file
113 Map
.UsePools(*Cache
.HeaderP
->Pools
,sizeof(Cache
.HeaderP
->Pools
)/sizeof(Cache
.HeaderP
->Pools
[0]));
114 if (Cache
.VS
!= _system
->VS
)
116 _error
->Error(_("Cache has an incompatible versioning system"));
121 Cache
.HeaderP
->Dirty
= true;
122 Map
.Sync(0,sizeof(pkgCache::Header
));
125 // CacheGenerator::~pkgCacheGenerator - Destructor /*{{{*/
126 // ---------------------------------------------------------------------
127 /* We sync the data then unset the dirty flag in two steps so as to
128 advoid a problem during a crash */
129 pkgCacheGenerator::~pkgCacheGenerator()
131 if (_error
->PendingError() == true)
133 if (Map
.Sync() == false)
136 Cache
.HeaderP
->Dirty
= false;
137 Cache
.HeaderP
->CacheFileSize
= Map
.Size();
138 Map
.Sync(0,sizeof(pkgCache::Header
));
141 void pkgCacheGenerator::ReMap(void const * const oldMap
, void const * const newMap
) {/*{{{*/
142 if (oldMap
== newMap
)
145 if (_config
->FindB("Debug::pkgCacheGen", false))
146 std::clog
<< "Remaping from " << oldMap
<< " to " << newMap
<< std::endl
;
150 CurrentFile
+= (pkgCache::PackageFile
const * const) newMap
- (pkgCache::PackageFile
const * const) oldMap
;
152 for (size_t i
= 0; i
< _count(UniqHash
); ++i
)
153 if (UniqHash
[i
] != 0)
154 UniqHash
[i
] += (pkgCache::StringItem
const * const) newMap
- (pkgCache::StringItem
const * const) oldMap
;
156 for (std::vector
<pkgCache::GrpIterator
*>::const_iterator i
= Dynamic
<pkgCache::GrpIterator
>::toReMap
.begin();
157 i
!= Dynamic
<pkgCache::GrpIterator
>::toReMap
.end(); ++i
)
158 (*i
)->ReMap(oldMap
, newMap
);
159 for (std::vector
<pkgCache::PkgIterator
*>::const_iterator i
= Dynamic
<pkgCache::PkgIterator
>::toReMap
.begin();
160 i
!= Dynamic
<pkgCache::PkgIterator
>::toReMap
.end(); ++i
)
161 (*i
)->ReMap(oldMap
, newMap
);
162 for (std::vector
<pkgCache::VerIterator
*>::const_iterator i
= Dynamic
<pkgCache::VerIterator
>::toReMap
.begin();
163 i
!= Dynamic
<pkgCache::VerIterator
>::toReMap
.end(); ++i
)
164 (*i
)->ReMap(oldMap
, newMap
);
165 for (std::vector
<pkgCache::DepIterator
*>::const_iterator i
= Dynamic
<pkgCache::DepIterator
>::toReMap
.begin();
166 i
!= Dynamic
<pkgCache::DepIterator
>::toReMap
.end(); ++i
)
167 (*i
)->ReMap(oldMap
, newMap
);
168 for (std::vector
<pkgCache::DescIterator
*>::const_iterator i
= Dynamic
<pkgCache::DescIterator
>::toReMap
.begin();
169 i
!= Dynamic
<pkgCache::DescIterator
>::toReMap
.end(); ++i
)
170 (*i
)->ReMap(oldMap
, newMap
);
171 for (std::vector
<pkgCache::PrvIterator
*>::const_iterator i
= Dynamic
<pkgCache::PrvIterator
>::toReMap
.begin();
172 i
!= Dynamic
<pkgCache::PrvIterator
>::toReMap
.end(); ++i
)
173 (*i
)->ReMap(oldMap
, newMap
);
174 for (std::vector
<pkgCache::PkgFileIterator
*>::const_iterator i
= Dynamic
<pkgCache::PkgFileIterator
>::toReMap
.begin();
175 i
!= Dynamic
<pkgCache::PkgFileIterator
>::toReMap
.end(); ++i
)
176 (*i
)->ReMap(oldMap
, newMap
);
178 // CacheGenerator::WriteStringInMap /*{{{*/
179 map_stringitem_t
pkgCacheGenerator::WriteStringInMap(const char *String
,
180 const unsigned long &Len
) {
181 void const * const oldMap
= Map
.Data();
182 map_stringitem_t
const index
= Map
.WriteString(String
, Len
);
184 ReMap(oldMap
, Map
.Data());
188 // CacheGenerator::WriteStringInMap /*{{{*/
189 map_stringitem_t
pkgCacheGenerator::WriteStringInMap(const char *String
) {
190 void const * const oldMap
= Map
.Data();
191 map_stringitem_t
const index
= Map
.WriteString(String
);
193 ReMap(oldMap
, Map
.Data());
197 map_pointer_t
pkgCacheGenerator::AllocateInMap(const unsigned long &size
) {/*{{{*/
198 void const * const oldMap
= Map
.Data();
199 map_pointer_t
const index
= Map
.Allocate(size
);
201 ReMap(oldMap
, Map
.Data());
205 // CacheGenerator::MergeList - Merge the package list /*{{{*/
206 // ---------------------------------------------------------------------
207 /* This provides the generation of the entries in the cache. Each loop
208 goes through a single package record from the underlying parse engine. */
209 bool pkgCacheGenerator::MergeList(ListParser
&List
,
210 pkgCache::VerIterator
*OutVer
)
214 unsigned int Counter
= 0;
215 while (List
.Step() == true)
217 string
const PackageName
= List
.Package();
218 if (PackageName
.empty() == true)
222 if (Counter
% 100 == 0 && Progress
!= 0)
223 Progress
->Progress(List
.Offset());
225 string Arch
= List
.Architecture();
226 string
const Version
= List
.Version();
227 if (Version
.empty() == true && Arch
.empty() == true)
229 // package descriptions
230 if (MergeListGroup(List
, PackageName
) == false)
235 if (Arch
.empty() == true)
237 // use the pseudo arch 'none' for arch-less packages
239 /* We might built a SingleArchCache here, which we don't want to blow up
240 just for these :none packages to a proper MultiArchCache, so just ensure
241 that we have always a native package structure first for SingleArch */
242 pkgCache::PkgIterator NP
;
243 Dynamic
<pkgCache::PkgIterator
> DynPkg(NP
);
244 if (NewPackage(NP
, PackageName
, _config
->Find("APT::Architecture")) == false)
245 // TRANSLATOR: The first placeholder is a package name,
246 // the other two should be copied verbatim as they include debug info
247 return _error
->Error(_("Error occurred while processing %s (%s%d)"),
248 PackageName
.c_str(), "NewPackage", 0);
251 // Get a pointer to the package structure
252 pkgCache::PkgIterator Pkg
;
253 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
254 if (NewPackage(Pkg
, PackageName
, Arch
) == false)
255 // TRANSLATOR: The first placeholder is a package name,
256 // the other two should be copied verbatim as they include debug info
257 return _error
->Error(_("Error occurred while processing %s (%s%d)"),
258 PackageName
.c_str(), "NewPackage", 1);
261 if (Version
.empty() == true)
263 if (MergeListPackage(List
, Pkg
) == false)
268 if (MergeListVersion(List
, Pkg
, Version
, OutVer
) == false)
274 FoundFileDeps
|= List
.HasFileDeps();
279 if (Cache
.HeaderP
->PackageCount
>= std::numeric_limits
<map_id_t
>::max())
280 return _error
->Error(_("Wow, you exceeded the number of package "
281 "names this APT is capable of."));
282 if (Cache
.HeaderP
->VersionCount
>= std::numeric_limits
<map_id_t
>::max())
283 return _error
->Error(_("Wow, you exceeded the number of versions "
284 "this APT is capable of."));
285 if (Cache
.HeaderP
->DescriptionCount
>= std::numeric_limits
<map_id_t
>::max())
286 return _error
->Error(_("Wow, you exceeded the number of descriptions "
287 "this APT is capable of."));
288 if (Cache
.HeaderP
->DependsCount
>= std::numeric_limits
<map_id_t
>::max())
289 return _error
->Error(_("Wow, you exceeded the number of dependencies "
290 "this APT is capable of."));
292 FoundFileDeps
|= List
.HasFileDeps();
295 // CacheGenerator::MergeListGroup /*{{{*/
296 bool pkgCacheGenerator::MergeListGroup(ListParser
&List
, std::string
const &GrpName
)
298 pkgCache::GrpIterator Grp
= Cache
.FindGrp(GrpName
);
299 // a group has no data on it's own, only packages have it but these
300 // stanzas like this come from Translation- files to add descriptions,
301 // but without a version we don't need a description for it…
302 if (Grp
.end() == true)
304 Dynamic
<pkgCache::GrpIterator
> DynGrp(Grp
);
306 pkgCache::PkgIterator Pkg
;
307 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
308 for (Pkg
= Grp
.PackageList(); Pkg
.end() == false; Pkg
= Grp
.NextPkg(Pkg
))
309 if (MergeListPackage(List
, Pkg
) == false)
315 // CacheGenerator::MergeListPackage /*{{{*/
316 bool pkgCacheGenerator::MergeListPackage(ListParser
&List
, pkgCache::PkgIterator
&Pkg
)
318 // we first process the package, then the descriptions
319 // (for deb this package processing is in fact a no-op)
320 pkgCache::VerIterator
Ver(Cache
);
321 Dynamic
<pkgCache::VerIterator
> DynVer(Ver
);
322 if (List
.UsePackage(Pkg
, Ver
) == false)
323 return _error
->Error(_("Error occurred while processing %s (%s%d)"),
324 Pkg
.Name(), "UsePackage", 1);
326 // Find the right version to write the description
327 MD5SumValue CurMd5
= List
.Description_md5();
328 if (CurMd5
.Value().empty() == true && List
.Description("").empty() == true)
330 std::vector
<std::string
> availDesc
= List
.AvailableDescriptionLanguages();
331 for (Ver
= Pkg
.VersionList(); Ver
.end() == false; ++Ver
)
333 pkgCache::DescIterator VerDesc
= Ver
.DescriptionList();
335 // a version can only have one md5 describing it
336 if (VerDesc
.end() == true || MD5SumValue(VerDesc
.md5()) != CurMd5
)
339 map_stringitem_t md5idx
= VerDesc
->md5sum
;
340 for (std::vector
<std::string
>::const_iterator CurLang
= availDesc
.begin(); CurLang
!= availDesc
.end(); ++CurLang
)
342 // don't add a new description if we have one for the given
344 if (IsDuplicateDescription(VerDesc
, CurMd5
, *CurLang
) == true)
347 AddNewDescription(List
, Ver
, *CurLang
, CurMd5
, md5idx
);
350 // we can stop here as all "same" versions will share the description
357 // CacheGenerator::MergeListVersion /*{{{*/
358 bool pkgCacheGenerator::MergeListVersion(ListParser
&List
, pkgCache::PkgIterator
&Pkg
,
359 std::string
const &Version
, pkgCache::VerIterator
* &OutVer
)
361 pkgCache::VerIterator Ver
= Pkg
.VersionList();
362 Dynamic
<pkgCache::VerIterator
> DynVer(Ver
);
363 map_pointer_t
*LastVer
= &Pkg
->VersionList
;
364 void const * oldMap
= Map
.Data();
366 unsigned short const Hash
= List
.VersionHash();
367 if (Ver
.end() == false)
369 /* We know the list is sorted so we use that fact in the search.
370 Insertion of new versions is done with correct sorting */
372 for (; Ver
.end() == false; LastVer
= &Ver
->NextVer
, Ver
++)
374 Res
= Cache
.VS
->CmpVersion(Version
,Ver
.VerStr());
375 // Version is higher as current version - insert here
378 // Versionstrings are equal - is hash also equal?
379 if (Res
== 0 && List
.SameVersion(Hash
, Ver
) == true)
381 // proceed with the next till we have either the right
382 // or we found another version (which will be lower)
385 /* We already have a version for this item, record that we saw it */
386 if (Res
== 0 && Ver
.end() == false && Ver
->Hash
== Hash
)
388 if (List
.UsePackage(Pkg
,Ver
) == false)
389 return _error
->Error(_("Error occurred while processing %s (%s%d)"),
390 Pkg
.Name(), "UsePackage", 2);
392 if (NewFileVer(Ver
,List
) == false)
393 return _error
->Error(_("Error occurred while processing %s (%s%d)"),
394 Pkg
.Name(), "NewFileVer", 1);
396 // Read only a single record and return
408 map_pointer_t
const verindex
= NewVersion(Ver
, Version
, Pkg
.Index(), Hash
, *LastVer
);
409 if (verindex
== 0 && _error
->PendingError())
410 return _error
->Error(_("Error occurred while processing %s (%s%d)"),
411 Pkg
.Name(), "NewVersion", 1);
413 if (oldMap
!= Map
.Data())
414 LastVer
+= (map_pointer_t
const * const) Map
.Data() - (map_pointer_t
const * const) oldMap
;
417 if (unlikely(List
.NewVersion(Ver
) == false))
418 return _error
->Error(_("Error occurred while processing %s (%s%d)"),
419 Pkg
.Name(), "NewVersion", 2);
421 if (unlikely(List
.UsePackage(Pkg
,Ver
) == false))
422 return _error
->Error(_("Error occurred while processing %s (%s%d)"),
423 Pkg
.Name(), "UsePackage", 3);
425 if (unlikely(NewFileVer(Ver
,List
) == false))
426 return _error
->Error(_("Error occurred while processing %s (%s%d)"),
427 Pkg
.Name(), "NewFileVer", 2);
429 pkgCache::GrpIterator Grp
= Pkg
.Group();
430 Dynamic
<pkgCache::GrpIterator
> DynGrp(Grp
);
432 /* If it is the first version of this package we need to add implicit
433 Multi-Arch dependencies to all other package versions in the group now -
434 otherwise we just add them for this new version */
435 if (Pkg
.VersionList()->NextVer
== 0)
437 pkgCache::PkgIterator P
= Grp
.PackageList();
438 Dynamic
<pkgCache::PkgIterator
> DynP(P
);
439 for (; P
.end() != true; P
= Grp
.NextPkg(P
))
441 if (P
->ID
== Pkg
->ID
)
443 pkgCache::VerIterator V
= P
.VersionList();
444 Dynamic
<pkgCache::VerIterator
> DynV(V
);
445 for (; V
.end() != true; ++V
)
446 if (unlikely(AddImplicitDepends(V
, Pkg
) == false))
447 return _error
->Error(_("Error occurred while processing %s (%s%d)"),
448 Pkg
.Name(), "AddImplicitDepends", 1);
450 /* :none packages are packages without an architecture. They are forbidden by
451 debian-policy, so usually they will only be in (old) dpkg status files -
452 and dpkg will complain about them - and are pretty rare. We therefore do
453 usually not create conflicts while the parent is created, but only if a :none
454 package (= the target) appears. This creates incorrect dependencies on :none
455 for architecture-specific dependencies on the package we copy from, but we
456 will ignore this bug as architecture-specific dependencies are only allowed
457 in jessie and until then the :none packages should be extinct (hopefully).
458 In other words: This should work long enough to allow graceful removal of
459 these packages, it is not supposed to allow users to keep using them … */
460 if (strcmp(Pkg
.Arch(), "none") == 0)
462 pkgCache::PkgIterator M
= Grp
.FindPreferredPkg();
463 if (M
.end() == false && Pkg
!= M
)
465 pkgCache::DepIterator D
= M
.RevDependsList();
466 Dynamic
<pkgCache::DepIterator
> DynD(D
);
467 for (; D
.end() == false; ++D
)
469 if ((D
->Type
!= pkgCache::Dep::Conflicts
&&
470 D
->Type
!= pkgCache::Dep::DpkgBreaks
&&
471 D
->Type
!= pkgCache::Dep::Replaces
) ||
472 D
.ParentPkg().Group() == Grp
)
475 map_pointer_t
*OldDepLast
= NULL
;
476 pkgCache::VerIterator ConVersion
= D
.ParentVer();
477 Dynamic
<pkgCache::VerIterator
> DynV(ConVersion
);
478 // duplicate the Conflicts/Breaks/Replaces for :none arch
479 NewDepends(Pkg
, ConVersion
, D
->Version
,
480 D
->CompareOp
, D
->Type
, OldDepLast
);
485 if (unlikely(AddImplicitDepends(Grp
, Pkg
, Ver
) == false))
486 return _error
->Error(_("Error occurred while processing %s (%s%d)"),
487 Pkg
.Name(), "AddImplicitDepends", 2);
489 // Read only a single record and return
496 /* Record the Description(s) based on their master md5sum */
497 MD5SumValue CurMd5
= List
.Description_md5();
498 if (CurMd5
.Value().empty() == true && List
.Description("").empty() == true)
501 /* Before we add a new description we first search in the group for
502 a version with a description of the same MD5 - if so we reuse this
503 description group instead of creating our own for this version */
504 for (pkgCache::PkgIterator P
= Grp
.PackageList();
505 P
.end() == false; P
= Grp
.NextPkg(P
))
507 for (pkgCache::VerIterator V
= P
.VersionList();
508 V
.end() == false; ++V
)
510 if (V
->DescriptionList
== 0 || MD5SumValue(V
.DescriptionList().md5()) != CurMd5
)
512 Ver
->DescriptionList
= V
->DescriptionList
;
516 // We haven't found reusable descriptions, so add the first description(s)
517 map_stringitem_t md5idx
= Ver
->DescriptionList
== 0 ? 0 : Ver
.DescriptionList()->md5sum
;
518 std::vector
<std::string
> availDesc
= List
.AvailableDescriptionLanguages();
519 for (std::vector
<std::string
>::const_iterator CurLang
= availDesc
.begin(); CurLang
!= availDesc
.end(); ++CurLang
)
520 if (AddNewDescription(List
, Ver
, *CurLang
, CurMd5
, md5idx
) == false)
525 bool pkgCacheGenerator::AddNewDescription(ListParser
&List
, pkgCache::VerIterator
&Ver
, std::string
const &lang
, MD5SumValue
const &CurMd5
, map_stringitem_t
&md5idx
) /*{{{*/
527 pkgCache::DescIterator Desc
;
528 Dynamic
<pkgCache::DescIterator
> DynDesc(Desc
);
530 map_pointer_t
const descindex
= NewDescription(Desc
, lang
, CurMd5
, md5idx
);
531 if (unlikely(descindex
== 0 && _error
->PendingError()))
532 return _error
->Error(_("Error occurred while processing %s (%s%d)"),
533 Ver
.ParentPkg().Name(), "NewDescription", 1);
535 md5idx
= Desc
->md5sum
;
536 Desc
->ParentPkg
= Ver
.ParentPkg().Index();
538 // we add at the end, so that the start is constant as we need
539 // that to be able to efficiently share these lists
540 pkgCache::DescIterator VerDesc
= Ver
.DescriptionList(); // old value might be invalid after ReMap
541 for (;VerDesc
.end() == false && VerDesc
->NextDesc
!= 0; ++VerDesc
);
542 map_pointer_t
* const LastNextDesc
= (VerDesc
.end() == true) ? &Ver
->DescriptionList
: &VerDesc
->NextDesc
;
543 *LastNextDesc
= descindex
;
545 if (NewFileDesc(Desc
,List
) == false)
546 return _error
->Error(_("Error occurred while processing %s (%s%d)"),
547 Ver
.ParentPkg().Name(), "NewFileDesc", 1);
553 // CacheGenerator::MergeFileProvides - Merge file provides /*{{{*/
554 // ---------------------------------------------------------------------
555 /* If we found any file depends while parsing the main list we need to
556 resolve them. Since it is undesired to load the entire list of files
557 into the cache as virtual packages we do a two stage effort. MergeList
558 identifies the file depends and this creates Provdies for them by
559 re-parsing all the indexs. */
560 bool pkgCacheGenerator::MergeFileProvides(ListParser
&List
)
564 unsigned int Counter
= 0;
565 while (List
.Step() == true)
567 string PackageName
= List
.Package();
568 if (PackageName
.empty() == true)
570 string Version
= List
.Version();
571 if (Version
.empty() == true)
574 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(PackageName
);
575 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
576 if (Pkg
.end() == true)
577 return _error
->Error(_("Error occurred while processing %s (%s%d)"),
578 PackageName
.c_str(), "FindPkg", 1);
580 if (Counter
% 100 == 0 && Progress
!= 0)
581 Progress
->Progress(List
.Offset());
583 unsigned short Hash
= List
.VersionHash();
584 pkgCache::VerIterator Ver
= Pkg
.VersionList();
585 Dynamic
<pkgCache::VerIterator
> DynVer(Ver
);
586 for (; Ver
.end() == false; ++Ver
)
588 if (List
.SameVersion(Hash
, Ver
) == true && Version
== Ver
.VerStr())
590 if (List
.CollectFileProvides(Cache
,Ver
) == false)
591 return _error
->Error(_("Error occurred while processing %s (%s%d)"),
592 PackageName
.c_str(), "CollectFileProvides", 1);
597 if (Ver
.end() == true)
598 _error
->Warning(_("Package %s %s was not found while processing file dependencies"),PackageName
.c_str(),Version
.c_str());
604 // CacheGenerator::NewGroup - Add a new group /*{{{*/
605 // ---------------------------------------------------------------------
606 /* This creates a new group structure and adds it to the hash table */
607 bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator
&Grp
, const string
&Name
)
609 Grp
= Cache
.FindGrp(Name
);
610 if (Grp
.end() == false)
614 map_pointer_t
const Group
= AllocateInMap(sizeof(pkgCache::Group
));
615 if (unlikely(Group
== 0))
618 Grp
= pkgCache::GrpIterator(Cache
, Cache
.GrpP
+ Group
);
619 map_pointer_t
const idxName
= WriteStringInMap(Name
);
620 if (unlikely(idxName
== 0))
624 // Insert it into the hash table
625 unsigned long const Hash
= Cache
.Hash(Name
);
626 map_pointer_t
*insertAt
= &Cache
.HeaderP
->GrpHashTable()[Hash
];
627 while (*insertAt
!= 0 && strcasecmp(Name
.c_str(), Cache
.StrP
+ (Cache
.GrpP
+ *insertAt
)->Name
) > 0)
628 insertAt
= &(Cache
.GrpP
+ *insertAt
)->Next
;
629 Grp
->Next
= *insertAt
;
632 Grp
->ID
= Cache
.HeaderP
->GroupCount
++;
636 // CacheGenerator::NewPackage - Add a new package /*{{{*/
637 // ---------------------------------------------------------------------
638 /* This creates a new package structure and adds it to the hash table */
639 bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator
&Pkg
,const string
&Name
,
640 const string
&Arch
) {
641 pkgCache::GrpIterator Grp
;
642 Dynamic
<pkgCache::GrpIterator
> DynGrp(Grp
);
643 if (unlikely(NewGroup(Grp
, Name
) == false))
646 Pkg
= Grp
.FindPkg(Arch
);
647 if (Pkg
.end() == false)
651 map_pointer_t
const Package
= AllocateInMap(sizeof(pkgCache::Package
));
652 if (unlikely(Package
== 0))
654 Pkg
= pkgCache::PkgIterator(Cache
,Cache
.PkgP
+ Package
);
656 // Insert the package into our package list
657 if (Grp
->FirstPackage
== 0) // the group is new
659 Grp
->FirstPackage
= Package
;
660 // Insert it into the hash table
661 map_id_t
const Hash
= Cache
.Hash(Name
);
662 map_pointer_t
*insertAt
= &Cache
.HeaderP
->PkgHashTable()[Hash
];
663 while (*insertAt
!= 0 && strcasecmp(Name
.c_str(), Cache
.StrP
+ (Cache
.GrpP
+ (Cache
.PkgP
+ *insertAt
)->Group
)->Name
) > 0)
664 insertAt
= &(Cache
.PkgP
+ *insertAt
)->Next
;
665 Pkg
->Next
= *insertAt
;
668 else // Group the Packages together
670 // this package is the new last package
671 pkgCache::PkgIterator
LastPkg(Cache
, Cache
.PkgP
+ Grp
->LastPackage
);
672 Pkg
->Next
= LastPkg
->Next
;
673 LastPkg
->Next
= Package
;
675 Grp
->LastPackage
= Package
;
677 // Set the name, arch and the ID
679 #pragma GCC diagnostic push
680 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
682 Pkg
->Name
= Grp
->Name
;
684 #pragma GCC diagnostic pop
686 Pkg
->Group
= Grp
.Index();
687 // all is mapped to the native architecture
688 map_stringitem_t
const idxArch
= (Arch
== "all") ? Cache
.HeaderP
->Architecture
: WriteUniqString(Arch
.c_str());
689 if (unlikely(idxArch
== 0))
692 Pkg
->ID
= Cache
.HeaderP
->PackageCount
++;
697 // CacheGenerator::AddImplicitDepends /*{{{*/
698 bool pkgCacheGenerator::AddImplicitDepends(pkgCache::GrpIterator
&G
,
699 pkgCache::PkgIterator
&P
,
700 pkgCache::VerIterator
&V
)
702 // copy P.Arch() into a string here as a cache remap
703 // in NewDepends() later may alter the pointer location
704 string Arch
= P
.Arch() == NULL
? "" : P
.Arch();
705 map_pointer_t
*OldDepLast
= NULL
;
706 /* MultiArch handling introduces a lot of implicit Dependencies:
707 - MultiArch: same → Co-Installable if they have the same version
708 - All others conflict with all other group members */
709 bool const coInstall
= ((V
->MultiArch
& pkgCache::Version::Same
) == pkgCache::Version::Same
);
710 pkgCache::PkgIterator D
= G
.PackageList();
711 Dynamic
<pkgCache::PkgIterator
> DynD(D
);
712 map_stringitem_t
const VerStrIdx
= V
->VerStr
;
713 for (; D
.end() != true; D
= G
.NextPkg(D
))
715 if (Arch
== D
.Arch() || D
->VersionList
== 0)
717 /* We allow only one installed arch at the time
718 per group, therefore each group member conflicts
719 with all other group members */
720 if (coInstall
== true)
722 // Replaces: ${self}:other ( << ${binary:Version})
723 NewDepends(D
, V
, VerStrIdx
,
724 pkgCache::Dep::Less
, pkgCache::Dep::Replaces
,
726 // Breaks: ${self}:other (!= ${binary:Version})
727 NewDepends(D
, V
, VerStrIdx
,
728 pkgCache::Dep::NotEquals
, pkgCache::Dep::DpkgBreaks
,
731 // Conflicts: ${self}:other
733 pkgCache::Dep::NoOp
, pkgCache::Dep::Conflicts
,
739 bool pkgCacheGenerator::AddImplicitDepends(pkgCache::VerIterator
&V
,
740 pkgCache::PkgIterator
&D
)
742 /* MultiArch handling introduces a lot of implicit Dependencies:
743 - MultiArch: same → Co-Installable if they have the same version
744 - All others conflict with all other group members */
745 map_pointer_t
*OldDepLast
= NULL
;
746 bool const coInstall
= ((V
->MultiArch
& pkgCache::Version::Same
) == pkgCache::Version::Same
);
747 if (coInstall
== true)
749 map_stringitem_t
const VerStrIdx
= V
->VerStr
;
750 // Replaces: ${self}:other ( << ${binary:Version})
751 NewDepends(D
, V
, VerStrIdx
,
752 pkgCache::Dep::Less
, pkgCache::Dep::Replaces
,
754 // Breaks: ${self}:other (!= ${binary:Version})
755 NewDepends(D
, V
, VerStrIdx
,
756 pkgCache::Dep::NotEquals
, pkgCache::Dep::DpkgBreaks
,
759 // Conflicts: ${self}:other
761 pkgCache::Dep::NoOp
, pkgCache::Dep::Conflicts
,
768 // CacheGenerator::NewFileVer - Create a new File<->Version association /*{{{*/
769 // ---------------------------------------------------------------------
771 bool pkgCacheGenerator::NewFileVer(pkgCache::VerIterator
&Ver
,
774 if (CurrentFile
== 0)
778 map_pointer_t
const VerFile
= AllocateInMap(sizeof(pkgCache::VerFile
));
782 pkgCache::VerFileIterator
VF(Cache
,Cache
.VerFileP
+ VerFile
);
783 VF
->File
= CurrentFile
- Cache
.PkgFileP
;
785 // Link it to the end of the list
786 map_pointer_t
*Last
= &Ver
->FileList
;
787 for (pkgCache::VerFileIterator V
= Ver
.FileList(); V
.end() == false; ++V
)
789 VF
->NextFile
= *Last
;
792 VF
->Offset
= List
.Offset();
793 VF
->Size
= List
.Size();
794 if (Cache
.HeaderP
->MaxVerFileSize
< VF
->Size
)
795 Cache
.HeaderP
->MaxVerFileSize
= VF
->Size
;
796 Cache
.HeaderP
->VerFileCount
++;
801 // CacheGenerator::NewVersion - Create a new Version /*{{{*/
802 // ---------------------------------------------------------------------
803 /* This puts a version structure in the linked list */
804 map_pointer_t
pkgCacheGenerator::NewVersion(pkgCache::VerIterator
&Ver
,
805 const string
&VerStr
,
806 map_pointer_t
const ParentPkg
,
807 unsigned short const Hash
,
808 map_pointer_t
const Next
)
811 map_pointer_t
const Version
= AllocateInMap(sizeof(pkgCache::Version
));
816 Ver
= pkgCache::VerIterator(Cache
,Cache
.VerP
+ Version
);
817 //Dynamic<pkgCache::VerIterator> DynV(Ver); // caller MergeListVersion already takes care of it
819 Ver
->ParentPkg
= ParentPkg
;
821 Ver
->ID
= Cache
.HeaderP
->VersionCount
++;
823 // try to find the version string in the group for reuse
824 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
825 pkgCache::GrpIterator Grp
= Pkg
.Group();
826 if (Pkg
.end() == false && Grp
.end() == false)
828 for (pkgCache::PkgIterator P
= Grp
.PackageList(); P
.end() == false; P
= Grp
.NextPkg(P
))
832 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
834 int const cmp
= strcmp(V
.VerStr(), VerStr
.c_str());
837 Ver
->VerStr
= V
->VerStr
;
845 // haven't found the version string, so create
846 map_stringitem_t
const idxVerStr
= WriteStringInMap(VerStr
);
847 if (unlikely(idxVerStr
== 0))
849 Ver
->VerStr
= idxVerStr
;
853 // CacheGenerator::NewFileDesc - Create a new File<->Desc association /*{{{*/
854 // ---------------------------------------------------------------------
856 bool pkgCacheGenerator::NewFileDesc(pkgCache::DescIterator
&Desc
,
859 if (CurrentFile
== 0)
863 map_pointer_t
const DescFile
= AllocateInMap(sizeof(pkgCache::DescFile
));
867 pkgCache::DescFileIterator
DF(Cache
,Cache
.DescFileP
+ DescFile
);
868 DF
->File
= CurrentFile
- Cache
.PkgFileP
;
870 // Link it to the end of the list
871 map_pointer_t
*Last
= &Desc
->FileList
;
872 for (pkgCache::DescFileIterator D
= Desc
.FileList(); D
.end() == false; ++D
)
875 DF
->NextFile
= *Last
;
878 DF
->Offset
= List
.Offset();
879 DF
->Size
= List
.Size();
880 if (Cache
.HeaderP
->MaxDescFileSize
< DF
->Size
)
881 Cache
.HeaderP
->MaxDescFileSize
= DF
->Size
;
882 Cache
.HeaderP
->DescFileCount
++;
887 // CacheGenerator::NewDescription - Create a new Description /*{{{*/
888 // ---------------------------------------------------------------------
889 /* This puts a description structure in the linked list */
890 map_pointer_t
pkgCacheGenerator::NewDescription(pkgCache::DescIterator
&Desc
,
892 const MD5SumValue
&md5sum
,
893 map_stringitem_t
const idxmd5str
)
896 map_pointer_t
const Description
= AllocateInMap(sizeof(pkgCache::Description
));
897 if (Description
== 0)
901 Desc
= pkgCache::DescIterator(Cache
,Cache
.DescP
+ Description
);
902 Desc
->ID
= Cache
.HeaderP
->DescriptionCount
++;
903 map_stringitem_t
const idxlanguage_code
= WriteUniqString(Lang
);
904 if (unlikely(idxlanguage_code
== 0))
906 Desc
->language_code
= idxlanguage_code
;
909 Desc
->md5sum
= idxmd5str
;
912 map_stringitem_t
const idxmd5sum
= WriteStringInMap(md5sum
.Value());
913 if (unlikely(idxmd5sum
== 0))
915 Desc
->md5sum
= idxmd5sum
;
921 // CacheGenerator::NewDepends - Create a dependency element /*{{{*/
922 // ---------------------------------------------------------------------
923 /* This creates a dependency element in the tree. It is linked to the
924 version and to the package that it is pointing to. */
925 bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator
&Pkg
,
926 pkgCache::VerIterator
&Ver
,
927 string
const &Version
,
928 unsigned int const &Op
,
929 unsigned int const &Type
,
930 map_stringitem_t
* &OldDepLast
)
932 map_stringitem_t index
= 0;
933 if (Version
.empty() == false)
935 int const CmpOp
= Op
& 0x0F;
936 // =-deps are used (79:1) for lockstep on same-source packages (e.g. data-packages)
937 if (CmpOp
== pkgCache::Dep::Equals
&& strcmp(Version
.c_str(), Ver
.VerStr()) == 0)
942 void const * const oldMap
= Map
.Data();
943 index
= WriteStringInMap(Version
);
944 if (unlikely(index
== 0))
946 if (OldDepLast
!= 0 && oldMap
!= Map
.Data())
947 OldDepLast
+= (map_pointer_t
const * const) Map
.Data() - (map_pointer_t
const * const) oldMap
;
950 return NewDepends(Pkg
, Ver
, index
, Op
, Type
, OldDepLast
);
952 bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator
&Pkg
,
953 pkgCache::VerIterator
&Ver
,
954 map_pointer_t
const Version
,
955 unsigned int const &Op
,
956 unsigned int const &Type
,
957 map_pointer_t
* &OldDepLast
)
959 void const * const oldMap
= Map
.Data();
961 map_pointer_t
const Dependency
= AllocateInMap(sizeof(pkgCache::Dependency
));
962 if (unlikely(Dependency
== 0))
966 pkgCache::DepIterator
Dep(Cache
,Cache
.DepP
+ Dependency
);
967 Dynamic
<pkgCache::DepIterator
> DynDep(Dep
);
968 Dep
->ParentVer
= Ver
.Index();
971 Dep
->Version
= Version
;
972 Dep
->ID
= Cache
.HeaderP
->DependsCount
++;
974 // Link it to the package
975 Dep
->Package
= Pkg
.Index();
976 Dep
->NextRevDepends
= Pkg
->RevDepends
;
977 Pkg
->RevDepends
= Dep
.Index();
979 // Do we know where to link the Dependency to?
980 if (OldDepLast
== NULL
)
982 OldDepLast
= &Ver
->DependsList
;
983 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
984 OldDepLast
= &D
->NextDepends
;
985 } else if (oldMap
!= Map
.Data())
986 OldDepLast
+= (map_pointer_t
const * const) Map
.Data() - (map_pointer_t
const * const) oldMap
;
988 Dep
->NextDepends
= *OldDepLast
;
989 *OldDepLast
= Dep
.Index();
990 OldDepLast
= &Dep
->NextDepends
;
995 // ListParser::NewDepends - Create the environment for a new dependency /*{{{*/
996 // ---------------------------------------------------------------------
997 /* This creates a Group and the Package to link this dependency to if
998 needed and handles also the caching of the old endpoint */
999 bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator
&Ver
,
1000 const string
&PackageName
,
1002 const string
&Version
,
1006 pkgCache::GrpIterator Grp
;
1007 Dynamic
<pkgCache::GrpIterator
> DynGrp(Grp
);
1008 if (unlikely(Owner
->NewGroup(Grp
, PackageName
) == false))
1011 // Locate the target package
1012 pkgCache::PkgIterator Pkg
= Grp
.FindPkg(Arch
);
1013 // we don't create 'none' packages and their dependencies if we can avoid it …
1014 if (Pkg
.end() == true && Arch
== "none" && strcmp(Ver
.ParentPkg().Arch(), "none") != 0)
1016 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
1017 if (Pkg
.end() == true) {
1018 if (unlikely(Owner
->NewPackage(Pkg
, PackageName
, Arch
) == false))
1022 // Is it a file dependency?
1023 if (unlikely(PackageName
[0] == '/'))
1024 FoundFileDeps
= true;
1026 /* Caching the old end point speeds up generation substantially */
1027 if (OldDepVer
!= Ver
) {
1032 return Owner
->NewDepends(Pkg
, Ver
, Version
, Op
, Type
, OldDepLast
);
1035 // ListParser::NewProvides - Create a Provides element /*{{{*/
1036 // ---------------------------------------------------------------------
1038 bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator
&Ver
,
1039 const string
&PkgName
,
1040 const string
&PkgArch
,
1041 const string
&Version
)
1043 pkgCache
&Cache
= Owner
->Cache
;
1045 // We do not add self referencing provides
1046 if (Ver
.ParentPkg().Name() == PkgName
&& (PkgArch
== Ver
.ParentPkg().Arch() ||
1047 (PkgArch
== "all" && strcmp((Cache
.StrP
+ Cache
.HeaderP
->Architecture
), Ver
.ParentPkg().Arch()) == 0)))
1051 map_pointer_t
const Provides
= Owner
->AllocateInMap(sizeof(pkgCache::Provides
));
1052 if (unlikely(Provides
== 0))
1054 Cache
.HeaderP
->ProvidesCount
++;
1057 pkgCache::PrvIterator
Prv(Cache
,Cache
.ProvideP
+ Provides
,Cache
.PkgP
);
1058 Dynamic
<pkgCache::PrvIterator
> DynPrv(Prv
);
1059 Prv
->Version
= Ver
.Index();
1060 Prv
->NextPkgProv
= Ver
->ProvidesList
;
1061 Ver
->ProvidesList
= Prv
.Index();
1062 if (Version
.empty() == false) {
1063 map_stringitem_t
const idxProvideVersion
= WriteString(Version
);
1064 Prv
->ProvideVersion
= idxProvideVersion
;
1065 if (unlikely(idxProvideVersion
== 0))
1069 // Locate the target package
1070 pkgCache::PkgIterator Pkg
;
1071 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
1072 if (unlikely(Owner
->NewPackage(Pkg
,PkgName
, PkgArch
) == false))
1075 // Link it to the package
1076 Prv
->ParentPkg
= Pkg
.Index();
1077 Prv
->NextProvides
= Pkg
->ProvidesList
;
1078 Pkg
->ProvidesList
= Prv
.Index();
1083 bool pkgCacheGenerator::ListParser::SameVersion(unsigned short const Hash
,/*{{{*/
1084 pkgCache::VerIterator
const &Ver
)
1086 return Hash
== Ver
->Hash
;
1089 // CacheGenerator::SelectFile - Select the current file being parsed /*{{{*/
1090 // ---------------------------------------------------------------------
1091 /* This is used to select which file is to be associated with all newly
1092 added versions. The caller is responsible for setting the IMS fields. */
1093 bool pkgCacheGenerator::SelectFile(const string
&File
,const string
&Site
,
1094 const pkgIndexFile
&Index
,
1095 unsigned long Flags
)
1097 // Get some space for the structure
1098 map_pointer_t
const idxFile
= AllocateInMap(sizeof(*CurrentFile
));
1099 if (unlikely(idxFile
== 0))
1101 CurrentFile
= Cache
.PkgFileP
+ idxFile
;
1104 map_stringitem_t
const idxFileName
= WriteStringInMap(File
);
1105 map_stringitem_t
const idxSite
= WriteUniqString(Site
);
1106 if (unlikely(idxFileName
== 0 || idxSite
== 0))
1108 CurrentFile
->FileName
= idxFileName
;
1109 CurrentFile
->Site
= idxSite
;
1110 CurrentFile
->NextFile
= Cache
.HeaderP
->FileList
;
1111 CurrentFile
->Flags
= Flags
;
1112 CurrentFile
->ID
= Cache
.HeaderP
->PackageFileCount
;
1113 map_stringitem_t
const idxIndexType
= WriteUniqString(Index
.GetType()->Label
);
1114 if (unlikely(idxIndexType
== 0))
1116 CurrentFile
->IndexType
= idxIndexType
;
1118 Cache
.HeaderP
->FileList
= CurrentFile
- Cache
.PkgFileP
;
1119 Cache
.HeaderP
->PackageFileCount
++;
1122 Progress
->SubProgress(Index
.Size());
1126 // CacheGenerator::WriteUniqueString - Insert a unique string /*{{{*/
1127 // ---------------------------------------------------------------------
1128 /* This is used to create handles to strings. Given the same text it
1129 always returns the same number */
1130 map_stringitem_t
pkgCacheGenerator::WriteUniqString(const char *S
,
1133 /* We use a very small transient hash table here, this speeds up generation
1134 by a fair amount on slower machines */
1135 pkgCache::StringItem
*&Bucket
= UniqHash
[(S
[0]*5 + S
[1]) % _count(UniqHash
)];
1137 stringcmp(S
,S
+Size
,Cache
.StrP
+ Bucket
->String
) == 0)
1138 return Bucket
->String
;
1140 // Search for an insertion point
1141 pkgCache::StringItem
*I
= Cache
.StringItemP
+ Cache
.HeaderP
->StringList
;
1143 map_stringitem_t
*Last
= &Cache
.HeaderP
->StringList
;
1144 for (; I
!= Cache
.StringItemP
; Last
= &I
->NextItem
,
1145 I
= Cache
.StringItemP
+ I
->NextItem
)
1147 Res
= stringcmp(S
,S
+Size
,Cache
.StrP
+ I
->String
);
1160 void const * const oldMap
= Map
.Data();
1161 map_pointer_t
const Item
= AllocateInMap(sizeof(pkgCache::StringItem
));
1165 map_stringitem_t
const idxString
= WriteStringInMap(S
,Size
);
1166 if (unlikely(idxString
== 0))
1168 if (oldMap
!= Map
.Data()) {
1169 Last
+= (map_pointer_t
const * const) Map
.Data() - (map_pointer_t
const * const) oldMap
;
1170 I
+= (pkgCache::StringItem
const * const) Map
.Data() - (pkgCache::StringItem
const * const) oldMap
;
1174 // Fill in the structure
1175 pkgCache::StringItem
*ItemP
= Cache
.StringItemP
+ Item
;
1176 ItemP
->NextItem
= I
- Cache
.StringItemP
;
1177 ItemP
->String
= idxString
;
1180 return ItemP
->String
;
1183 // CheckValidity - Check that a cache is up-to-date /*{{{*/
1184 // ---------------------------------------------------------------------
1185 /* This just verifies that each file in the list of index files exists,
1186 has matching attributes with the cache and the cache does not have
1188 static bool CheckValidity(const string
&CacheFile
,
1189 pkgSourceList
&List
,
1194 bool const Debug
= _config
->FindB("Debug::pkgCacheGen", false);
1195 // No file, certainly invalid
1196 if (CacheFile
.empty() == true || FileExists(CacheFile
) == false)
1199 std::clog
<< "CacheFile doesn't exist" << std::endl
;
1203 if (List
.GetLastModifiedTime() > GetModificationTime(CacheFile
))
1206 std::clog
<< "sources.list is newer than the cache" << std::endl
;
1211 FileFd
CacheF(CacheFile
,FileFd::ReadOnly
);
1212 SPtr
<MMap
> Map
= new MMap(CacheF
,0);
1213 pkgCache
Cache(Map
);
1214 if (_error
->PendingError() == true || Map
->Size() == 0)
1217 std::clog
<< "Errors are pending or Map is empty()" << std::endl
;
1222 /* Now we check every index file, see if it is in the cache,
1223 verify the IMS data and check that it is on the disk too.. */
1224 SPtrArray
<bool> Visited
= new bool[Cache
.HeaderP
->PackageFileCount
];
1225 memset(Visited
,0,sizeof(*Visited
)*Cache
.HeaderP
->PackageFileCount
);
1226 for (; Start
!= End
; ++Start
)
1229 std::clog
<< "Checking PkgFile " << (*Start
)->Describe() << ": ";
1230 if ((*Start
)->HasPackages() == false)
1233 std::clog
<< "Has NO packages" << std::endl
;
1237 if ((*Start
)->Exists() == false)
1239 #if 0 // mvo: we no longer give a message here (Default Sources spec)
1240 _error
->WarningE("stat",_("Couldn't stat source package list %s"),
1241 (*Start
)->Describe().c_str());
1244 std::clog
<< "file doesn't exist" << std::endl
;
1248 // FindInCache is also expected to do an IMS check.
1249 pkgCache::PkgFileIterator File
= (*Start
)->FindInCache(Cache
);
1250 if (File
.end() == true)
1253 std::clog
<< "FindInCache returned end-Pointer" << std::endl
;
1257 Visited
[File
->ID
] = true;
1259 std::clog
<< "with ID " << File
->ID
<< " is valid" << std::endl
;
1262 for (unsigned I
= 0; I
!= Cache
.HeaderP
->PackageFileCount
; I
++)
1263 if (Visited
[I
] == false)
1266 std::clog
<< "File with ID" << I
<< " wasn't visited" << std::endl
;
1270 if (_error
->PendingError() == true)
1274 std::clog
<< "Validity failed because of pending errors:" << std::endl
;
1275 _error
->DumpErrors();
1282 *OutMap
= Map
.UnGuard();
1286 // ComputeSize - Compute the total size of a bunch of files /*{{{*/
1287 // ---------------------------------------------------------------------
1288 /* Size is kind of an abstract notion that is only used for the progress
1290 static map_filesize_t
ComputeSize(FileIterator Start
,FileIterator End
)
1292 map_filesize_t TotalSize
= 0;
1293 for (; Start
< End
; ++Start
)
1295 if ((*Start
)->HasPackages() == false)
1297 TotalSize
+= (*Start
)->Size();
1302 // BuildCache - Merge the list of index files into the cache /*{{{*/
1303 // ---------------------------------------------------------------------
1305 static bool BuildCache(pkgCacheGenerator
&Gen
,
1306 OpProgress
*Progress
,
1307 map_filesize_t
&CurrentSize
,map_filesize_t TotalSize
,
1308 FileIterator Start
, FileIterator End
)
1311 for (I
= Start
; I
!= End
; ++I
)
1313 if ((*I
)->HasPackages() == false)
1316 if ((*I
)->Exists() == false)
1319 if ((*I
)->FindInCache(Gen
.GetCache()).end() == false)
1321 _error
->Warning("Duplicate sources.list entry %s",
1322 (*I
)->Describe().c_str());
1326 map_filesize_t Size
= (*I
)->Size();
1327 if (Progress
!= NULL
)
1328 Progress
->OverallProgress(CurrentSize
,TotalSize
,Size
,_("Reading package lists"));
1329 CurrentSize
+= Size
;
1331 if ((*I
)->Merge(Gen
,Progress
) == false)
1335 if (Gen
.HasFileDeps() == true)
1337 if (Progress
!= NULL
)
1339 TotalSize
= ComputeSize(Start
, End
);
1341 for (I
= Start
; I
!= End
; ++I
)
1343 map_filesize_t Size
= (*I
)->Size();
1344 if (Progress
!= NULL
)
1345 Progress
->OverallProgress(CurrentSize
,TotalSize
,Size
,_("Collecting File Provides"));
1346 CurrentSize
+= Size
;
1347 if ((*I
)->MergeFileProvides(Gen
,Progress
) == false)
1355 // CacheGenerator::CreateDynamicMMap - load an mmap with configuration options /*{{{*/
1356 DynamicMMap
* pkgCacheGenerator::CreateDynamicMMap(FileFd
*CacheF
, unsigned long Flags
) {
1357 map_filesize_t
const MapStart
= _config
->FindI("APT::Cache-Start", 24*1024*1024);
1358 map_filesize_t
const MapGrow
= _config
->FindI("APT::Cache-Grow", 1*1024*1024);
1359 map_filesize_t
const MapLimit
= _config
->FindI("APT::Cache-Limit", 0);
1360 Flags
|= MMap::Moveable
;
1361 if (_config
->FindB("APT::Cache-Fallback", false) == true)
1362 Flags
|= MMap::Fallback
;
1364 return new DynamicMMap(*CacheF
, Flags
, MapStart
, MapGrow
, MapLimit
);
1366 return new DynamicMMap(Flags
, MapStart
, MapGrow
, MapLimit
);
1369 // CacheGenerator::MakeStatusCache - Construct the status cache /*{{{*/
1370 // ---------------------------------------------------------------------
1371 /* This makes sure that the status cache (the cache that has all
1372 index files from the sources list and all local ones) is ready
1373 to be mmaped. If OutMap is not zero then a MMap object representing
1374 the cache will be stored there. This is pretty much mandetory if you
1375 are using AllowMem. AllowMem lets the function be run as non-root
1376 where it builds the cache 'fast' into a memory buffer. */
1377 APT_DEPRECATED
bool pkgMakeStatusCache(pkgSourceList
&List
,OpProgress
&Progress
,
1378 MMap
**OutMap
, bool AllowMem
)
1379 { return pkgCacheGenerator::MakeStatusCache(List
, &Progress
, OutMap
, AllowMem
); }
1380 bool pkgCacheGenerator::MakeStatusCache(pkgSourceList
&List
,OpProgress
*Progress
,
1381 MMap
**OutMap
,bool AllowMem
)
1383 bool const Debug
= _config
->FindB("Debug::pkgCacheGen", false);
1385 std::vector
<pkgIndexFile
*> Files
;
1386 for (std::vector
<metaIndex
*>::const_iterator i
= List
.begin();
1390 std::vector
<pkgIndexFile
*> *Indexes
= (*i
)->GetIndexFiles();
1391 for (std::vector
<pkgIndexFile
*>::const_iterator j
= Indexes
->begin();
1392 j
!= Indexes
->end();
1394 Files
.push_back (*j
);
1397 map_filesize_t
const EndOfSource
= Files
.size();
1398 if (_system
->AddStatusFiles(Files
) == false)
1401 // Decide if we can write to the files..
1402 string
const CacheFile
= _config
->FindFile("Dir::Cache::pkgcache");
1403 string
const SrcCacheFile
= _config
->FindFile("Dir::Cache::srcpkgcache");
1405 // ensure the cache directory exists
1406 if (CacheFile
.empty() == false || SrcCacheFile
.empty() == false)
1408 string dir
= _config
->FindDir("Dir::Cache");
1409 size_t const len
= dir
.size();
1410 if (len
> 5 && dir
.find("/apt/", len
- 6, 5) == len
- 5)
1411 dir
= dir
.substr(0, len
- 5);
1412 if (CacheFile
.empty() == false)
1413 CreateDirectory(dir
, flNotFile(CacheFile
));
1414 if (SrcCacheFile
.empty() == false)
1415 CreateDirectory(dir
, flNotFile(SrcCacheFile
));
1418 // Decide if we can write to the cache
1419 bool Writeable
= false;
1420 if (CacheFile
.empty() == false)
1421 Writeable
= access(flNotFile(CacheFile
).c_str(),W_OK
) == 0;
1423 if (SrcCacheFile
.empty() == false)
1424 Writeable
= access(flNotFile(SrcCacheFile
).c_str(),W_OK
) == 0;
1426 std::clog
<< "Do we have write-access to the cache files? " << (Writeable
? "YES" : "NO") << std::endl
;
1428 if (Writeable
== false && AllowMem
== false && CacheFile
.empty() == false)
1429 return _error
->Error(_("Unable to write to %s"),flNotFile(CacheFile
).c_str());
1431 if (Progress
!= NULL
)
1432 Progress
->OverallProgress(0,1,1,_("Reading package lists"));
1434 // Cache is OK, Fin.
1435 if (CheckValidity(CacheFile
, List
, Files
.begin(),Files
.end(),OutMap
) == true)
1437 if (Progress
!= NULL
)
1438 Progress
->OverallProgress(1,1,1,_("Reading package lists"));
1440 std::clog
<< "pkgcache.bin is valid - no need to build anything" << std::endl
;
1443 else if (Debug
== true)
1444 std::clog
<< "pkgcache.bin is NOT valid" << std::endl
;
1446 /* At this point we know we need to reconstruct the package cache,
1448 SPtr
<FileFd
> CacheF
;
1449 SPtr
<DynamicMMap
> Map
;
1450 if (Writeable
== true && CacheFile
.empty() == false)
1452 _error
->PushToStack();
1453 unlink(CacheFile
.c_str());
1454 CacheF
= new FileFd(CacheFile
,FileFd::WriteAtomic
);
1455 fchmod(CacheF
->Fd(),0644);
1456 Map
= CreateDynamicMMap(CacheF
, MMap::Public
);
1457 if (_error
->PendingError() == true)
1459 delete CacheF
.UnGuard();
1460 delete Map
.UnGuard();
1462 std::clog
<< "Open filebased MMap FAILED" << std::endl
;
1464 if (AllowMem
== false)
1466 _error
->MergeWithStack();
1469 _error
->RevertToStack();
1473 _error
->MergeWithStack();
1475 std::clog
<< "Open filebased MMap" << std::endl
;
1478 if (Writeable
== false || CacheFile
.empty() == true)
1480 // Just build it in memory..
1481 Map
= CreateDynamicMMap(NULL
);
1483 std::clog
<< "Open memory Map (not filebased)" << std::endl
;
1486 // Lets try the source cache.
1487 map_filesize_t CurrentSize
= 0;
1488 map_filesize_t TotalSize
= 0;
1489 if (CheckValidity(SrcCacheFile
, List
, Files
.begin(),
1490 Files
.begin()+EndOfSource
) == true)
1493 std::clog
<< "srcpkgcache.bin is valid - populate MMap with it." << std::endl
;
1494 // Preload the map with the source cache
1495 FileFd
SCacheF(SrcCacheFile
,FileFd::ReadOnly
);
1496 map_pointer_t
const alloc
= Map
->RawAllocate(SCacheF
.Size());
1497 if ((alloc
== 0 && _error
->PendingError())
1498 || SCacheF
.Read((unsigned char *)Map
->Data() + alloc
,
1499 SCacheF
.Size()) == false)
1502 TotalSize
= ComputeSize(Files
.begin()+EndOfSource
,Files
.end());
1504 // Build the status cache
1505 pkgCacheGenerator
Gen(Map
.Get(),Progress
);
1506 if (_error
->PendingError() == true)
1508 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1509 Files
.begin()+EndOfSource
,Files
.end()) == false)
1515 std::clog
<< "srcpkgcache.bin is NOT valid - rebuild" << std::endl
;
1516 TotalSize
= ComputeSize(Files
.begin(),Files
.end());
1518 // Build the source cache
1519 pkgCacheGenerator
Gen(Map
.Get(),Progress
);
1520 if (_error
->PendingError() == true)
1522 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1523 Files
.begin(),Files
.begin()+EndOfSource
) == false)
1527 if (Writeable
== true && SrcCacheFile
.empty() == false)
1529 FileFd
SCacheF(SrcCacheFile
,FileFd::WriteAtomic
);
1530 if (_error
->PendingError() == true)
1533 fchmod(SCacheF
.Fd(),0644);
1535 // Write out the main data
1536 if (SCacheF
.Write(Map
->Data(),Map
->Size()) == false)
1537 return _error
->Error(_("IO Error saving source cache"));
1540 // Write out the proper header
1541 Gen
.GetCache().HeaderP
->Dirty
= false;
1542 if (SCacheF
.Seek(0) == false ||
1543 SCacheF
.Write(Map
->Data(),sizeof(*Gen
.GetCache().HeaderP
)) == false)
1544 return _error
->Error(_("IO Error saving source cache"));
1545 Gen
.GetCache().HeaderP
->Dirty
= true;
1549 // Build the status cache
1550 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1551 Files
.begin()+EndOfSource
,Files
.end()) == false)
1555 std::clog
<< "Caches are ready for shipping" << std::endl
;
1557 if (_error
->PendingError() == true)
1563 delete Map
.UnGuard();
1564 *OutMap
= new MMap(*CacheF
,0);
1568 *OutMap
= Map
.UnGuard();
1575 // CacheGenerator::MakeOnlyStatusCache - Build only a status files cache/*{{{*/
1576 // ---------------------------------------------------------------------
1578 APT_DEPRECATED
bool pkgMakeOnlyStatusCache(OpProgress
&Progress
,DynamicMMap
**OutMap
)
1579 { return pkgCacheGenerator::MakeOnlyStatusCache(&Progress
, OutMap
); }
1580 bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress
*Progress
,DynamicMMap
**OutMap
)
1582 std::vector
<pkgIndexFile
*> Files
;
1583 map_filesize_t EndOfSource
= Files
.size();
1584 if (_system
->AddStatusFiles(Files
) == false)
1587 SPtr
<DynamicMMap
> Map
= CreateDynamicMMap(NULL
);
1588 map_filesize_t CurrentSize
= 0;
1589 map_filesize_t TotalSize
= 0;
1591 TotalSize
= ComputeSize(Files
.begin()+EndOfSource
,Files
.end());
1593 // Build the status cache
1594 if (Progress
!= NULL
)
1595 Progress
->OverallProgress(0,1,1,_("Reading package lists"));
1596 pkgCacheGenerator
Gen(Map
.Get(),Progress
);
1597 if (_error
->PendingError() == true)
1599 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1600 Files
.begin()+EndOfSource
,Files
.end()) == false)
1603 if (_error
->PendingError() == true)
1605 *OutMap
= Map
.UnGuard();
1610 // IsDuplicateDescription /*{{{*/
1611 static bool IsDuplicateDescription(pkgCache::DescIterator Desc
,
1612 MD5SumValue
const &CurMd5
, std::string
const &CurLang
)
1614 // Descriptions in the same link-list have all the same md5
1615 if (Desc
.end() == true || MD5SumValue(Desc
.md5()) != CurMd5
)
1617 for (; Desc
.end() == false; ++Desc
)
1618 if (Desc
.LanguageCode() == CurLang
)
1623 // CacheGenerator::FinishCache /*{{{*/
1624 bool pkgCacheGenerator::FinishCache(OpProgress
* /*Progress*/)