]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/pkgcache.cc
parse version correctly from binary Source field
[apt.git] / apt-pkg / pkgcache.cc
index e8c95738e9673848ce6d27c932449a9195234bea..c9c338e1eff3370550a18d1072a91b0d4883385f 100644 (file)
 
 #include <stddef.h>
 #include <string.h>
 
 #include <stddef.h>
 #include <string.h>
-#include <ostream>
+#include <sstream>
+#include <algorithm>
 #include <vector>
 #include <string>
 #include <sys/stat.h>
 #include <vector>
 #include <string>
 #include <sys/stat.h>
+#include <zlib.h>
 
 #include <apti18n.h>
                                                                        /*}}}*/
 
 using std::string;
 
 #include <apti18n.h>
                                                                        /*}}}*/
 
 using std::string;
+using APT::StringView;
 
 
 // Cache::Header::Header - Constructor                                 /*{{{*/
 
 
 // Cache::Header::Header - Constructor                                 /*{{{*/
@@ -56,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);
    /* 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, 0);
+   APT_HEADER_SET(MinorVersion, 5);
    APT_HEADER_SET(Dirty, false);
 
    APT_HEADER_SET(HeaderSz, sizeof(pkgCache::Header));
    APT_HEADER_SET(Dirty, false);
 
    APT_HEADER_SET(HeaderSz, sizeof(pkgCache::Header));
@@ -92,7 +95,7 @@ pkgCache::Header::Header()
    VerSysName = 0;
    Architecture = 0;
    SetArchitectures(0);
    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;
    memset(Pools,0,sizeof(Pools));
 
    CacheFileSize = 0;
@@ -172,9 +175,6 @@ bool pkgCache::ReMap(bool const &Errorchecks)
        HeaderP->CheckSizes(DefHeader) == false)
       return _error->Error(_("The package cache file is an incompatible version"));
 
        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"));
 
    if (HeaderP->VerSysName == 0 || HeaderP->Architecture == 0 || HeaderP->GetArchitectures() == 0)
       return _error->Error(_("The package cache file is corrupted"));
 
@@ -192,6 +192,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());
 
         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;
 }
                                                                        /*}}}*/
    return true;
 }
                                                                        /*}}}*/
@@ -200,53 +207,69 @@ 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) */
 /* 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
 {
 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)
    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
 {
    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();
 }
    return Hash % HeaderP->GetHashTableSize();
 }
-                                                                       /*}}}*/
-// Cache::SingleArchFindPkg - Locate a package by name                 /*{{{*/
-// ---------------------------------------------------------------------
-/* Returns 0 on error, pointer to the package otherwise
-   The multiArch enabled methods will fallback to this one as it is (a bit)
-   faster for single arch environments and realworld is mostly singlearch… */
-pkgCache::PkgIterator pkgCache::SingleArchFindPkg(const string &Name)
+
+uint32_t pkgCache::CacheHash()
 {
 {
-   // Look at the hash bucket
-   Package *Pkg = PkgP + HeaderP->PkgHashTableP()[Hash(Name)];
-   for (; Pkg != PkgP; Pkg = PkgP + Pkg->NextPackage)
-   {
-      int const cmp = strcmp(Name.c_str(), StrP + (GrpP + Pkg->Group)->Name);
-      if (cmp == 0)
-        return PkgIterator(*this, Pkg);
-      else if (cmp < 0)
-        break;
+   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 PkgIterator(*this,0);
+
+   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) {
 }
                                                                        /*}}}*/
 // 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");
        if (found == string::npos)
           return FindPkg(Name, "native");
-       string 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 with all archs.
-          If you want any arch from a given pkg, use FindPkg(pkg,arch) */
+       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") */
        if (Arch == "any")
                return FindPkg(Name, "any");
        return FindPkg(Name.substr(0, found), Arch);
        if (Arch == "any")
                return FindPkg(Name, "any");
        return FindPkg(Name.substr(0, found), Arch);
@@ -256,6 +279,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) {
 // ---------------------------------------------------------------------
 /* 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) */
        /* 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) */
@@ -270,13 +297,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) {
 // ---------------------------------------------------------------------
 /* 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) {
        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)
                if (cmp == 0)
                        return GrpIterator(*this, Grp);
                else if (cmp < 0)
@@ -328,7 +359,7 @@ const char *pkgCache::DepType(unsigned char Type)
 /* */
 const char *pkgCache::Priority(unsigned char Prio)
 {
 /* */
 const char *pkgCache::Priority(unsigned char Prio)
 {
-   const char *Mapping[] = {0,_("important"),_("required"),_("standard"),
+   const char *Mapping[] = {0,_("required"),_("important"),_("standard"),
                             _("optional"),_("extra")};
    if (Prio < _count(Mapping))
       return Mapping[Prio];
                             _("optional"),_("extra")};
    if (Prio < _count(Mapping))
       return Mapping[Prio];
@@ -339,29 +370,26 @@ 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 {
 // ---------------------------------------------------------------------
 /* 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);
 
        /* If we accept any package we simply return the "first"
        if (unlikely(IsGood() == false || S->FirstPackage == 0))
                return PkgIterator(*Owner, 0);
 
        /* If we accept any package we simply return the "first"
-          package in this group (the last one added). */
+          package in this group */
        if (Arch == "any")
                return PkgIterator(*Owner, Owner->PkgP + S->FirstPackage);
        if (Arch == "any")
                return PkgIterator(*Owner, Owner->PkgP + S->FirstPackage);
-
-       char const* const myArch = Owner->NativeArch();
-       /* Most of the time the package for our native architecture is
-          the one we add at first to the cache, but this would be the
-          last one we check, so we do it now. */
-       if (Arch == "native" || Arch == myArch || Arch == "all") {
-               pkgCache::Package *Pkg = Owner->PkgP + S->LastPackage;
-               if (strcmp(myArch, Owner->StrP + Pkg->Arch) == 0)
-                       return PkgIterator(*Owner, Pkg);
-               Arch = myArch;
-       }
+       if (Arch == "native" || Arch == "all")
+               Arch = Owner->NativeArch();
 
        // Iterate over the list to find the matching arch
        for (pkgCache::Package *Pkg = PackageList(); Pkg != Owner->PkgP;
             Pkg = Owner->PkgP + Pkg->NextPackage) {
 
        // 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;
                        return PkgIterator(*Owner, Pkg);
                if ((Owner->PkgP + S->LastPackage) == Pkg)
                        break;
@@ -374,7 +402,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 {
 // ---------------------------------------------------------------------
 /* 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;
 
        if (Pkg.end() == false && (PreferNonVirtual == false || Pkg->VersionList != 0))
                return Pkg;
 
@@ -386,7 +414,7 @@ pkgCache::PkgIterator pkgCache::GrpIterator::FindPreferredPkg(bool const &Prefer
                        return Pkg;
        }
        // packages without an architecture
                        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;
 
        if (Pkg.end() == false && (PreferNonVirtual == false || Pkg->VersionList != 0))
                return Pkg;
 
@@ -545,7 +573,7 @@ std::string pkgCache::PkgIterator::FullName(bool const &Pretty) const
 {
    string fullname = Name();
    if (Pretty == false ||
 {
    string fullname = Name();
    if (Pretty == false ||
-       (strcmp(Arch(), "all") != 0 &&
+       (strcmp(Arch(), "all") != 0 && strcmp(Arch(), "any") != 0 &&
        strcmp(Owner->NativeArch(), Arch()) != 0))
       return fullname.append(":").append(Arch());
    return fullname;
        strcmp(Owner->NativeArch(), Arch()) != 0))
       return fullname.append(":").append(Arch());
    return fullname;
@@ -866,10 +894,32 @@ pkgCache::VerFileIterator pkgCache::VerIterator::NewestFile() const
 // ---------------------------------------------------------------------
 /* This describes the version from a release-centric manner. The output is a 
    list of Label:Version/Archive */
 // ---------------------------------------------------------------------
 /* This describes the version from a release-centric manner. The output is a 
    list of Label:Version/Archive */
+static std::string PkgFileIteratorToRelString(pkgCache::PkgFileIterator const &File)
+{
+   std::string Res;
+   if (File.Label() != 0)
+      Res = Res + File.Label() + ':';
+
+   if (File.Archive() != 0)
+   {
+      if (File.Version() == 0)
+        Res += File.Archive();
+      else
+        Res = Res + File.Version() + '/' +  File.Archive();
+   }
+   else
+   {
+      // No release file, print the host name that this came from
+      if (File.Site() == 0 || File.Site()[0] == 0)
+        Res += "localhost";
+      else
+        Res += File.Site();
+   }
+   return Res;
+}
 string pkgCache::VerIterator::RelStr() const
 {
 string pkgCache::VerIterator::RelStr() const
 {
-   bool First = true;
-   string Res;
+   std::vector<std::string> RelStrs;
    for (pkgCache::VerFileIterator I = this->FileList(); I.end() == false; ++I)
    {
       // Do not print 'not source' entries'
    for (pkgCache::VerFileIterator I = this->FileList(); I.end() == false; ++I)
    {
       // Do not print 'not source' entries'
@@ -877,58 +927,21 @@ string pkgCache::VerIterator::RelStr() const
       if (File.Flagged(pkgCache::Flag::NotSource))
         continue;
 
       if (File.Flagged(pkgCache::Flag::NotSource))
         continue;
 
-      // See if we have already printed this out..
-      bool Seen = false;
-      for (pkgCache::VerFileIterator J = this->FileList(); I != J; ++J)
-      {
-        pkgCache::PkgFileIterator const File2 = J.File();
-        if (File2.Label() == 0 || File.Label() == 0)
-           continue;
-
-        if (strcmp(File.Label(),File2.Label()) != 0)
-           continue;
-        
-        if (File2.Version() == File.Version())
-        {
-           Seen = true;
-           break;
-        }
-        if (File2.Version() == 0 || File.Version() == 0)
-           break;
-        if (strcmp(File.Version(),File2.Version()) == 0)
-           Seen = true;
-      }
-      
-      if (Seen == true)
+      std::string const RS = PkgFileIteratorToRelString(File);
+      if (std::find(RelStrs.begin(), RelStrs.end(), RS) != RelStrs.end())
         continue;
         continue;
-      
-      if (First == false)
-        Res += ", ";
-      else
-        First = false;
-      
-      if (File.Label() != 0)
-        Res = Res + File.Label() + ':';
 
 
-      if (File.Archive() != 0)
-      {
-        if (File.Version() == 0)
-           Res += File.Archive();
-        else
-           Res = Res + File.Version() + '/' +  File.Archive();
-      }
-      else
-      {
-        // No release file, print the host name that this came from
-        if (File.Site() == 0 || File.Site()[0] == 0)
-           Res += "localhost";
-        else
-           Res += File.Site();
-      }      
+      RelStrs.push_back(RS);
+   }
+   std::ostringstream os;
+   if (likely(RelStrs.empty() == false))
+   {
+      std::copy(RelStrs.begin(), RelStrs.end()-1, std::ostream_iterator<std::string>(os, ", "));
+      os << *RelStrs.rbegin();
    }
    if (S->ParentPkg != 0)
    }
    if (S->ParentPkg != 0)
-      Res.append(" [").append(Arch()).append("]");
-   return Res;
+      os << " [" << Arch() << "]";
+   return os.str();
 }
                                                                        /*}}}*/
 // VerIterator::MultiArchType - string representing MultiArch flag     /*{{{*/
 }
                                                                        /*}}}*/
 // VerIterator::MultiArchType - string representing MultiArch flag     /*{{{*/