]> git.saurik.com Git - apt.git/commitdiff
Add support for calculating hashes over the entire cache
authorJulian Andres Klode <jak@debian.org>
Tue, 29 Dec 2015 14:11:11 +0000 (15:11 +0100)
committerJulian Andres Klode <jak@debian.org>
Tue, 29 Dec 2015 15:37:57 +0000 (16:37 +0100)
apt-pkg/pkgcache.cc
apt-pkg/pkgcache.h
apt-pkg/pkgcachegen.cc

index dd25fc51d06e459f430cde9b3249393b1324d7da..347a0954e1b2c71ea03d3ca8ee5cf5bda41151e6 100644 (file)
@@ -39,6 +39,7 @@
 #include <vector>
 #include <string>
 #include <sys/stat.h>
+#include <zlib.h>
 
 #include <apti18n.h>
                                                                        /*}}}*/
@@ -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<const unsigned char *>(&header),
+                  sizeof(header));
+
+   if (Map.Size() > sizeof(header)) {
+      adler = adler32(adler,
+                     static_cast<const unsigned char *>(GetMap().Data()) + sizeof(header),
+                     GetMap().Size() - sizeof(header));
+   }
+
+   return adler;
+}
                                                                        /*}}}*/
 // Cache::FindPkg - Locate a package by name                           /*{{{*/
 // ---------------------------------------------------------------------
index e44fd544cc8cba091b3fe20a5e3f40a90d61f952..7acfc01ba84408c28fb01378afce6f1f4e1bf65b 100644 (file)
@@ -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;
index 6d3b74361528bf0e5fd5b0abe8c48abaa5336ff7..e5fd121f8aaebe5eaabf8c2bbcce724ed79ef943 100644 (file)
@@ -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"));