X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/027010953973bc868262a110e79610880610728d..769e06cf07625f4a2f5c84340ef6af697d7b0894:/apt-pkg/pkgcache.cc diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index e65e37bca..b4c232f8c 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -39,11 +39,13 @@ #include #include #include +#include #include /*}}}*/ using std::string; +using APT::StringView; // Cache::Header::Header - Constructor /*{{{*/ @@ -57,7 +59,7 @@ pkgCache::Header::Header() /* Whenever the structures change the major version should be bumped, whenever the generator changes the minor version should be bumped. */ APT_HEADER_SET(MajorVersion, 10); - APT_HEADER_SET(MinorVersion, 2); + APT_HEADER_SET(MinorVersion, 7); APT_HEADER_SET(Dirty, false); APT_HEADER_SET(HeaderSz, sizeof(pkgCache::Header)); @@ -93,7 +95,7 @@ pkgCache::Header::Header() VerSysName = 0; Architecture = 0; SetArchitectures(0); - SetHashTableSize(_config->FindI("APT::Cache-HashTableSize", 10 * 1048)); + SetHashTableSize(_config->FindI("APT::Cache-HashTableSize", 50503)); memset(Pools,0,sizeof(Pools)); CacheFileSize = 0; @@ -125,7 +127,7 @@ bool pkgCache::Header::CheckSizes(Header &Against) const // --------------------------------------------------------------------- /* */ APT_IGNORE_DEPRECATED_PUSH -pkgCache::pkgCache(MMap *Map, bool DoMap) : Map(*Map), d(NULL) +pkgCache::pkgCache(MMap *Map, bool DoMap) : Map(*Map), VS(nullptr), d(NULL) { // call getArchitectures() with cached=false to ensure that the // architectures cache is re-evaulated. this is needed in cases @@ -173,9 +175,6 @@ bool pkgCache::ReMap(bool const &Errorchecks) HeaderP->CheckSizes(DefHeader) == false) return _error->Error(_("The package cache file is an incompatible version")); - if (Map.Size() < HeaderP->CacheFileSize) - return _error->Error(_("The package cache file is corrupted, it is too small")); - if (HeaderP->VerSysName == 0 || HeaderP->Architecture == 0 || HeaderP->GetArchitectures() == 0) return _error->Error(_("The package cache file is corrupted")); @@ -185,14 +184,23 @@ bool pkgCache::ReMap(bool const &Errorchecks) // Check the architecture std::vector archs = APT::Configuration::getArchitectures(); - std::vector::const_iterator a = archs.begin(); - std::string list = *a; - for (++a; a != archs.end(); ++a) - list.append(",").append(*a); + std::string list = ""; + for (auto const & arch : archs) { + if (!list.empty()) + list.append(","); + list.append(arch); + } if (_config->Find("APT::Architecture") != StrP + HeaderP->Architecture || list != StrP + HeaderP->GetArchitectures()) return _error->Error(_("The package cache was built for different architectures: %s vs %s"), StrP + HeaderP->GetArchitectures(), list.c_str()); + + auto hash = CacheHash(); + if (_config->FindB("Debug::pkgCacheGen", false)) + std::clog << "Opened cache with hash " << hash << ", expecting " << HeaderP->CacheFileSize << "\n"; + if (hash != HeaderP->CacheFileSize) + return _error->Error(_("The package cache file is corrupted, it has the wrong hash")); + return true; } /*}}}*/ @@ -201,30 +209,66 @@ bool pkgCache::ReMap(bool const &Errorchecks) /* This is used to generate the hash entries for the HashTable. With my package list from bo this function gets 94% table usage on a 512 item table (480 used items) */ +map_id_t pkgCache::sHash(StringView Str) const +{ + uint32_t Hash = 5381; + for (auto I = Str.begin(); I != Str.end(); ++I) + Hash = 33 * Hash + tolower_ascii(*I); + return Hash % HeaderP->GetHashTableSize(); +} map_id_t pkgCache::sHash(const string &Str) const { - unsigned long Hash = 0; + uint32_t Hash = 5381; for (string::const_iterator I = Str.begin(); I != Str.end(); ++I) - Hash = 41 * Hash + tolower_ascii(*I); + Hash = 33 * Hash + tolower_ascii((signed char)*I); return Hash % HeaderP->GetHashTableSize(); } map_id_t pkgCache::sHash(const char *Str) const { - unsigned long Hash = tolower_ascii(*Str); - for (const char *I = Str + 1; *I != 0; ++I) - Hash = 41 * Hash + tolower_ascii(*I); + uint32_t Hash = 5381; + for (const char *I = Str; *I != 0; ++I) + Hash = 33 * Hash + tolower_ascii((signed char)*I); return Hash % HeaderP->GetHashTableSize(); } + +uint32_t pkgCache::CacheHash() +{ + pkgCache::Header header = {}; + uLong adler = adler32(0L, Z_NULL, 0); + + if (Map.Size() < sizeof(header)) + return adler; + memcpy(&header, GetMap().Data(), sizeof(header)); + + header.Dirty = false; + header.CacheFileSize = 0; + + adler = adler32(adler, + reinterpret_cast(&header), + sizeof(header)); + + if (Map.Size() > sizeof(header)) { + adler = adler32(adler, + static_cast(GetMap().Data()) + sizeof(header), + GetMap().Size() - sizeof(header)); + } + + return adler; +} /*}}}*/ // Cache::FindPkg - Locate a package by name /*{{{*/ // --------------------------------------------------------------------- /* Returns 0 on error, pointer to the package otherwise */ pkgCache::PkgIterator pkgCache::FindPkg(const string &Name) { - size_t const found = Name.find(':'); + return FindPkg(StringView(Name)); +} + +pkgCache::PkgIterator pkgCache::FindPkg(StringView Name) { + auto const found = Name.rfind(':'); if (found == string::npos) return FindPkg(Name, "native"); - string const Arch = Name.substr(found+1); + auto const Arch = Name.substr(found+1); /* Beware: This is specialcased to handle pkg:any in dependencies as these are linked to virtual pkg:any named packages. If you want any arch from a pkg, use FindPkg(pkg,"any") */ @@ -237,6 +281,10 @@ pkgCache::PkgIterator pkgCache::FindPkg(const string &Name) { // --------------------------------------------------------------------- /* Returns 0 on error, pointer to the package otherwise */ pkgCache::PkgIterator pkgCache::FindPkg(const string &Name, string const &Arch) { + return FindPkg(StringView(Name), StringView(Arch)); +} + +pkgCache::PkgIterator pkgCache::FindPkg(StringView Name, StringView Arch) { /* We make a detour via the GrpIterator here as on a multi-arch environment a group is easier to find than a package (less entries in the buckets) */ @@ -251,13 +299,17 @@ pkgCache::PkgIterator pkgCache::FindPkg(const string &Name, string const &Arch) // --------------------------------------------------------------------- /* Returns End-Pointer on error, pointer to the group otherwise */ pkgCache::GrpIterator pkgCache::FindGrp(const string &Name) { + return FindGrp(StringView(Name)); +} + +pkgCache::GrpIterator pkgCache::FindGrp(StringView Name) { if (unlikely(Name.empty() == true)) return GrpIterator(*this,0); // Look at the hash bucket for the group Group *Grp = GrpP + HeaderP->GrpHashTableP()[sHash(Name)]; for (; Grp != GrpP; Grp = GrpP + Grp->Next) { - int const cmp = strcmp(Name.c_str(), StrP + Grp->Name); + int const cmp = Name.compare(ViewString(Grp->Name)); if (cmp == 0) return GrpIterator(*this, Grp); else if (cmp < 0) @@ -320,6 +372,12 @@ const char *pkgCache::Priority(unsigned char Prio) // --------------------------------------------------------------------- /* Returns an End-Pointer on error, pointer to the package otherwise */ pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) const { + return FindPkg(StringView(Arch)); +} +pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(const char *Arch) const { + return FindPkg(StringView(Arch)); +} +pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(StringView Arch) const { if (unlikely(IsGood() == false || S->FirstPackage == 0)) return PkgIterator(*Owner, 0); @@ -333,7 +391,7 @@ pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) const { // Iterate over the list to find the matching arch for (pkgCache::Package *Pkg = PackageList(); Pkg != Owner->PkgP; Pkg = Owner->PkgP + Pkg->NextPackage) { - if (stringcmp(Arch, Owner->StrP + Pkg->Arch) == 0) + if (Arch == Owner->ViewString(Pkg->Arch)) return PkgIterator(*Owner, Pkg); if ((Owner->PkgP + S->LastPackage) == Pkg) break; @@ -346,7 +404,7 @@ pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) const { // --------------------------------------------------------------------- /* Returns an End-Pointer on error, pointer to the package otherwise */ pkgCache::PkgIterator pkgCache::GrpIterator::FindPreferredPkg(bool const &PreferNonVirtual) const { - pkgCache::PkgIterator Pkg = FindPkg("native"); + pkgCache::PkgIterator Pkg = FindPkg(StringView("native", 6)); if (Pkg.end() == false && (PreferNonVirtual == false || Pkg->VersionList != 0)) return Pkg; @@ -358,7 +416,7 @@ pkgCache::PkgIterator pkgCache::GrpIterator::FindPreferredPkg(bool const &Prefer return Pkg; } // packages without an architecture - Pkg = FindPkg("none"); + Pkg = FindPkg(StringView("none", 4)); if (Pkg.end() == false && (PreferNonVirtual == false || Pkg->VersionList != 0)) return Pkg; @@ -442,7 +500,7 @@ pkgCache::PkgIterator::OkState pkgCache::PkgIterator::State() const if (S->CurrentState == pkgCache::State::UnPacked || S->CurrentState == pkgCache::State::HalfConfigured) - // we leave triggers alone complettely. dpkg deals with + // we leave triggers alone completely. dpkg deals with // them in a hard-to-predict manner and if they get // resolved by dpkg before apt run dpkg --configure on // the TriggersPending package dpkg returns a error @@ -495,7 +553,9 @@ operator<<(std::ostream& out, pkgCache::PkgIterator Pkg) return out << "invalid package"; string current = string(Pkg.CurVersion() == 0 ? "none" : Pkg.CurVersion()); +APT_IGNORE_DEPRECATED_PUSH string candidate = string(Pkg.CandVersion() == 0 ? "none" : Pkg.CandVersion()); +APT_IGNORE_DEPRECATED_POP string newest = string(Pkg.VersionList().end() ? "none" : Pkg.VersionList().VerStr()); out << Pkg.Name() << " [ " << Pkg.Arch() << " ] < " << current; @@ -744,7 +804,7 @@ bool pkgCache::DepIterator::IsImplicit() const return false; } /*}}}*/ -// ostream operator to handle string representation of a dependecy /*{{{*/ +// ostream operator to handle string representation of a dependency /*{{{*/ // --------------------------------------------------------------------- /* */ std::ostream& operator<<(std::ostream& out, pkgCache::DepIterator D) @@ -757,10 +817,12 @@ std::ostream& operator<<(std::ostream& out, pkgCache::DepIterator D) out << (P.end() ? "invalid pkg" : P.FullName(false)) << " " << D.DepType() << " on "; +APT_IGNORE_DEPRECATED_PUSH if (T.end() == true) out << "invalid pkg"; else out << T; +APT_IGNORE_DEPRECATED_POP if (D->Version != 0) out << " (" << D.CompType() << " " << D.TargetVer() << ")";