X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/074564d40c21cb063bf327e9151a4e24cd9534b5..769e06cf07625f4a2f5c84340ef6af697d7b0894:/apt-pkg/pkgcachegen.cc diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index 0dbac3df8..f0b5a982e 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -40,8 +40,8 @@ #include #include - -template using Dynamic = pkgCacheGenerator::Dynamic; /*}}}*/ + /*}}}*/ +template using Dynamic = pkgCacheGenerator::Dynamic; typedef std::vector::iterator FileIterator; template std::vector pkgCacheGenerator::Dynamic::toReMap; @@ -57,6 +57,9 @@ using APT::StringView; pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) : Map(*pMap), Cache(pMap,false), Progress(Prog), CurrentRlsFile(NULL), CurrentFile(NULL), d(NULL) +{ +} +bool pkgCacheGenerator::Start() { if (Map.Size() == 0) { @@ -67,7 +70,9 @@ pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) : bool const newError = _error->PendingError(); _error->MergeWithStack(); if (newError) - return; + return false; + if (Map.Size() <= 0) + return false; Map.UsePools(*Cache.HeaderP->Pools,sizeof(Cache.HeaderP->Pools)/sizeof(Cache.HeaderP->Pools[0])); @@ -76,16 +81,15 @@ pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) : // make room for the hashtables for packages and groups if (Map.RawAllocate(2 * (Cache.HeaderP->GetHashTableSize() * sizeof(map_pointer_t))) == 0) - return; + return false; map_stringitem_t const idxVerSysName = WriteStringInMap(_system->VS->Label); if (unlikely(idxVerSysName == 0)) - return; - Cache.HeaderP->VerSysName = idxVerSysName; + return false; map_stringitem_t const idxArchitecture = StoreString(MIXED, _config->Find("APT::Architecture")); if (unlikely(idxArchitecture == 0)) - return; - Cache.HeaderP->Architecture = idxArchitecture; + return false; + map_stringitem_t idxArchitectures; std::vector archs = APT::Configuration::getArchitectures(); if (archs.size() > 1) @@ -94,13 +98,17 @@ pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) : std::string list = *a; for (++a; a != archs.end(); ++a) list.append(",").append(*a); - map_stringitem_t const idxArchitectures = WriteStringInMap(list); + idxArchitectures = WriteStringInMap(list); if (unlikely(idxArchitectures == 0)) - return; - Cache.HeaderP->SetArchitectures(idxArchitectures); + return false; } else - Cache.HeaderP->SetArchitectures(idxArchitecture); + idxArchitectures = idxArchitecture; + + Cache.HeaderP = (pkgCache::Header *)Map.Data(); + Cache.HeaderP->VerSysName = idxVerSysName; + Cache.HeaderP->Architecture = idxArchitecture; + Cache.HeaderP->SetArchitectures(idxArchitectures); // Calculate the hash for the empty map, so ReMap does not fail Cache.HeaderP->CacheFileSize = Cache.CacheHash(); @@ -112,14 +120,12 @@ pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) : Cache.ReMap(); Map.UsePools(*Cache.HeaderP->Pools,sizeof(Cache.HeaderP->Pools)/sizeof(Cache.HeaderP->Pools[0])); if (Cache.VS != _system->VS) - { - _error->Error(_("Cache has an incompatible versioning system")); - return; - } + return _error->Error(_("Cache has an incompatible versioning system")); } Cache.HeaderP->Dirty = true; Map.Sync(0,sizeof(pkgCache::Header)); + return true; } /*}}}*/ // CacheGenerator::~pkgCacheGenerator - Destructor /*{{{*/ @@ -142,6 +148,10 @@ pkgCacheGenerator::~pkgCacheGenerator() } /*}}}*/ void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newMap, size_t oldSize) {/*{{{*/ + // Prevent multiple remaps of the same iterator. If seen.insert(iterator) + // returns (something, true) the iterator was not yet seen and we can + // remap it. + std::unordered_set seen; if (oldMap == newMap) return; @@ -155,29 +165,39 @@ void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newM for (std::vector::const_iterator i = Dynamic::toReMap.begin(); i != Dynamic::toReMap.end(); ++i) - (*i)->ReMap(oldMap, newMap); + if (std::get<1>(seen.insert(*i)) == true) + (*i)->ReMap(oldMap, newMap); for (std::vector::const_iterator i = Dynamic::toReMap.begin(); i != Dynamic::toReMap.end(); ++i) - (*i)->ReMap(oldMap, newMap); + if (std::get<1>(seen.insert(*i)) == true) + (*i)->ReMap(oldMap, newMap); for (std::vector::const_iterator i = Dynamic::toReMap.begin(); i != Dynamic::toReMap.end(); ++i) - (*i)->ReMap(oldMap, newMap); + if (std::get<1>(seen.insert(*i)) == true) + (*i)->ReMap(oldMap, newMap); for (std::vector::const_iterator i = Dynamic::toReMap.begin(); i != Dynamic::toReMap.end(); ++i) - (*i)->ReMap(oldMap, newMap); + if (std::get<1>(seen.insert(*i)) == true) + (*i)->ReMap(oldMap, newMap); for (std::vector::const_iterator i = Dynamic::toReMap.begin(); i != Dynamic::toReMap.end(); ++i) - (*i)->ReMap(oldMap, newMap); + if (std::get<1>(seen.insert(*i)) == true) + (*i)->ReMap(oldMap, newMap); for (std::vector::const_iterator i = Dynamic::toReMap.begin(); i != Dynamic::toReMap.end(); ++i) - (*i)->ReMap(oldMap, newMap); + if (std::get<1>(seen.insert(*i)) == true) + (*i)->ReMap(oldMap, newMap); for (std::vector::const_iterator i = Dynamic::toReMap.begin(); i != Dynamic::toReMap.end(); ++i) - (*i)->ReMap(oldMap, newMap); + if (std::get<1>(seen.insert(*i)) == true) + (*i)->ReMap(oldMap, newMap); for (std::vector::const_iterator i = Dynamic::toReMap.begin(); i != Dynamic::toReMap.end(); ++i) - (*i)->ReMap(oldMap, newMap); + if (std::get<1>(seen.insert(*i)) == true) + (*i)->ReMap(oldMap, newMap); for (APT::StringView* ViewP : Dynamic::toReMap) { + if (std::get<1>(seen.insert(ViewP)) == false) + continue; // Ignore views outside of the cache. if (ViewP->data() < static_cast(oldMap) || ViewP->data() > static_cast(oldMap) + oldSize) @@ -236,8 +256,10 @@ bool pkgCacheGenerator::MergeList(ListParser &List, if (Counter % 100 == 0 && Progress != 0) Progress->Progress(List.Offset()); - string Arch = List.Architecture(); - string const Version = List.Version(); + APT::StringView Arch = List.Architecture(); + Dynamic DynArch(Arch); + APT::StringView Version = List.Version(); + Dynamic DynVersion(Version); if (Version.empty() == true && Arch.empty() == true) { // package descriptions @@ -348,7 +370,7 @@ bool pkgCacheGenerator::MergeListPackage(ListParser &List, pkgCache::PkgIterator /*}}}*/ // CacheGenerator::MergeListVersion /*{{{*/ bool pkgCacheGenerator::MergeListVersion(ListParser &List, pkgCache::PkgIterator &Pkg, - std::string const &Version, pkgCache::VerIterator* &OutVer) + APT::StringView const &Version, pkgCache::VerIterator* &OutVer) { pkgCache::VerIterator Ver = Pkg.VersionList(); Dynamic DynVer(Ver); @@ -363,13 +385,28 @@ bool pkgCacheGenerator::MergeListVersion(ListParser &List, pkgCache::PkgIterator int Res = 1; for (; Ver.end() == false; LastVer = &Ver->NextVer, ++Ver) { - Res = Cache.VS->CmpVersion(Version,Ver.VerStr()); + char const * const VerStr = Ver.VerStr(); + Res = Cache.VS->DoCmpVersion(Version.data(), Version.data() + Version.length(), + VerStr, VerStr + strlen(VerStr)); // Version is higher as current version - insert here if (Res > 0) break; // Versionstrings are equal - is hash also equal? - if (Res == 0 && List.SameVersion(Hash, Ver) == true) - break; + if (Res == 0) + { + if (List.SameVersion(Hash, Ver) == true) + break; + // sort (volatile) sources above not-sources like the status file + if ((CurrentFile->Flags & pkgCache::Flag::NotSource) == 0) + { + auto VF = Ver.FileList(); + for (; VF.end() == false; ++VF) + if (VF.File().Flagged(pkgCache::Flag::NotSource) == false) + break; + if (VF.end() == true) + break; + } + } // proceed with the next till we have either the right // or we found another version (which will be lower) } @@ -709,9 +746,8 @@ bool pkgCacheGenerator::AddImplicitDepends(pkgCache::GrpIterator &G, pkgCache::PkgIterator &P, pkgCache::VerIterator &V) { - // copy P.Arch() into a string here as a cache remap - // in NewDepends() later may alter the pointer location - string Arch = P.Arch() == NULL ? "" : P.Arch(); + APT::StringView Arch = P.Arch() == NULL ? "" : P.Arch(); + Dynamic DynArch(Arch); map_pointer_t *OldDepLast = NULL; /* MultiArch handling introduces a lot of implicit Dependencies: - MultiArch: same → Co-Installable if they have the same version @@ -812,7 +848,7 @@ bool pkgCacheGenerator::NewFileVer(pkgCache::VerIterator &Ver, // --------------------------------------------------------------------- /* This puts a version structure in the linked list */ map_pointer_t pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver, - const string &VerStr, + APT::StringView const &VerStr, map_pointer_t const ParentPkg, unsigned short const Hash, map_pointer_t const Next) @@ -841,8 +877,8 @@ map_pointer_t pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver, continue; for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; ++V) { - int const cmp = strcmp(V.VerStr(), VerStr.c_str()); - if (cmp == 0) + int const cmp = strncmp(V.VerStr(), VerStr.data(), VerStr.length()); + if (cmp == 0 && V.VerStr()[VerStr.length()] == '\0') { Ver->VerStr = V->VerStr; return Version; @@ -1604,7 +1640,7 @@ static bool loadBackMMapFromFile(std::unique_ptr &Gen, if (CacheF.Read((unsigned char *)Map->Data() + alloc, CacheF.Size()) == false) return false; Gen.reset(new pkgCacheGenerator(Map.get(),Progress)); - return true; + return Gen->Start(); } bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress, MMap **OutMap, bool AllowMem) @@ -1710,6 +1746,8 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress if (Debug == true) std::clog << "srcpkgcache.bin is NOT valid - rebuild" << std::endl; Gen.reset(new pkgCacheGenerator(Map.get(),Progress)); + if (Gen->Start() == false) + return false; TotalSize += ComputeSize(&List, Files.begin(),Files.end()); if (BuildCache(*Gen, Progress, CurrentSize, TotalSize, &List, @@ -1735,7 +1773,7 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress } if (Debug == true) - std::clog << "Caches done. Now bring in the volatile files (if any)" << std::endl; + std::clog << "Caches done. " << (volatile_fine ? "No volatile files, so we are done here." : "Now bring in the volatile files") << std::endl; if (volatile_fine == false) { @@ -1787,7 +1825,7 @@ bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **O if (Progress != NULL) Progress->OverallProgress(0,1,1,_("Reading package lists")); pkgCacheGenerator Gen(Map.get(),Progress); - if (_error->PendingError() == true) + if (Gen.Start() == false || _error->PendingError() == true) return false; if (BuildCache(Gen,Progress,CurrentSize,TotalSize, NULL, Files.begin(), Files.end()) == false)