From 25c7a09d4a207bac875817559580f62c9ee07cb5 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 29 Dec 2015 15:11:11 +0100 Subject: Add support for calculating hashes over the entire cache --- apt-pkg/pkgcache.cc | 36 +++++++++++++++++++++++++++++++++--- apt-pkg/pkgcache.h | 4 +++- apt-pkg/pkgcachegen.cc | 8 +++++++- 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index dd25fc51d..347a0954e 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -39,6 +39,7 @@ #include #include #include +#include #include /*}}}*/ @@ -173,9 +174,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")); @@ -193,6 +191,13 @@ bool pkgCache::ReMap(bool const &Errorchecks) 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; } /*}}}*/ @@ -216,6 +221,31 @@ map_id_t pkgCache::sHash(const char *Str) const Hash = 33 * Hash + tolower_ascii(*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 /*{{{*/ // --------------------------------------------------------------------- diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h index e44fd544c..7acfc01ba 100644 --- a/apt-pkg/pkgcache.h +++ b/apt-pkg/pkgcache.h @@ -224,6 +224,8 @@ class pkgCache /*{{{*/ inline map_id_t Hash(const std::string &S) const {return sHash(S);} inline map_id_t Hash(const char *S) const {return sHash(S);} + APT_HIDDEN uint32_t CacheHash(); + // Useful transformation things static const char *Priority(unsigned char Priority); @@ -364,7 +366,7 @@ struct pkgCache::Header map_pointer_t * PkgHashTableP() const { return (map_pointer_t*) (this + 1); } map_pointer_t * GrpHashTableP() const { return PkgHashTableP() + GetHashTableSize(); } - /** \brief Size of the complete cache file */ + /** \brief Hash of the file (TODO: Rename) */ map_filesize_small_t CacheFileSize; bool CheckSizes(Header &Against) const APT_PURE; diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index 6d3b74361..e5fd121f8 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -101,6 +101,8 @@ pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) : else Cache.HeaderP->SetArchitectures(idxArchitecture); + // Calculate the hash for the empty map, so ReMap does not fail + Cache.HeaderP->CacheFileSize = Cache.CacheHash(); Cache.ReMap(); } else @@ -131,7 +133,10 @@ pkgCacheGenerator::~pkgCacheGenerator() return; Cache.HeaderP->Dirty = false; - Cache.HeaderP->CacheFileSize = Map.Size(); + Cache.HeaderP->CacheFileSize = Cache.CacheHash(); + + if (_config->FindB("Debug::pkgCacheGen", false)) + std::clog << "Produced cache with hash " << Cache.HeaderP->CacheFileSize << std::endl; Map.Sync(0,sizeof(pkgCache::Header)); } /*}}}*/ @@ -1534,6 +1539,7 @@ static bool writeBackMMapToFile(pkgCacheGenerator * const Gen, DynamicMMap * con // Write out the proper header Gen->GetCache().HeaderP->Dirty = false; + Gen->GetCache().HeaderP->CacheFileSize = Gen->GetCache().CacheHash(); if (SCacheF.Seek(0) == false || SCacheF.Write(Map->Data(),sizeof(*Gen->GetCache().HeaderP)) == false) return _error->Error(_("IO Error saving source cache")); -- cgit v1.2.3