]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/pkgcache.cc
headers are for declarations only
[apt.git] / apt-pkg / pkgcache.cc
index 67a2a709dbe4e1ef12cb66689f74112766063aba..ae04bc699351ec1d2cdc96aee5c45cec88b82bea 100644 (file)
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/aptconfiguration.h>
+#include <apt-pkg/mmap.h>
 #include <apt-pkg/macros.h>
 
+#include <stddef.h>
+#include <string.h>
+#include <ostream>
+#include <vector>
 #include <string>
 #include <sys/stat.h>
-#include <unistd.h>
-#include <ctype.h>
 
 #include <apti18n.h>
                                                                        /*}}}*/
@@ -51,13 +54,14 @@ pkgCache::Header::Header()
    
    /* Whenever the structures change the major version should be bumped,
       whenever the generator changes the minor version should be bumped. */
-   MajorVersion = 8;
-   MinorVersion = 1;
+   MajorVersion = 10;
+   MinorVersion = 0;
    Dirty = false;
    
    HeaderSz = sizeof(pkgCache::Header);
    GroupSz = sizeof(pkgCache::Group);
    PackageSz = sizeof(pkgCache::Package);
+   ReleaseFileSz = sizeof(pkgCache::ReleaseFile);
    PackageFileSz = sizeof(pkgCache::PackageFile);
    VersionSz = sizeof(pkgCache::Version);
    DescriptionSz = sizeof(pkgCache::Description);
@@ -71,6 +75,7 @@ pkgCache::Header::Header()
    VersionCount = 0;
    DescriptionCount = 0;
    DependsCount = 0;
+   ReleaseFileCount = 0;
    PackageFileCount = 0;
    VerFileCount = 0;
    DescFileCount = 0;
@@ -79,11 +84,14 @@ pkgCache::Header::Header()
    MaxDescFileSize = 0;
    
    FileList = 0;
-   StringList = 0;
+   RlsFileList = 0;
+#if APT_PKG_ABI < 413
+   APT_IGNORE_DEPRECATED(StringList = 0;)
+#endif
    VerSysName = 0;
    Architecture = 0;
-   memset(PkgHashTable,0,sizeof(PkgHashTable));
-   memset(GrpHashTable,0,sizeof(GrpHashTable));
+   SetArchitectures(0);
+   SetHashTableSize(_config->FindI("APT::Cache-HashTableSize", 10 * 1048));
    memset(Pools,0,sizeof(Pools));
 
    CacheFileSize = 0;
@@ -97,6 +105,7 @@ bool pkgCache::Header::CheckSizes(Header &Against) const
    if (HeaderSz == Against.HeaderSz &&
        GroupSz == Against.GroupSz &&
        PackageSz == Against.PackageSz &&
+       ReleaseFileSz == Against.ReleaseFileSz &&
        PackageFileSz == Against.PackageFileSz &&
        VersionSz == Against.VersionSz &&
        DescriptionSz == Against.DescriptionSz &&
@@ -112,7 +121,8 @@ bool pkgCache::Header::CheckSizes(Header &Against) const
 // Cache::pkgCache - Constructor                                       /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-pkgCache::pkgCache(MMap *Map, bool DoMap) : Map(*Map)
+APT_IGNORE_DEPRECATED_PUSH
+pkgCache::pkgCache(MMap *Map, bool DoMap) : Map(*Map), d(NULL)
 {
    // call getArchitectures() with cached=false to ensure that the 
    // architectures cache is re-evaulated. this is needed in cases
@@ -121,6 +131,7 @@ pkgCache::pkgCache(MMap *Map, bool DoMap) : Map(*Map)
    if (DoMap == true)
       ReMap();
 }
+APT_IGNORE_DEPRECATED_POP
                                                                        /*}}}*/
 // Cache::ReMap - Reopen the cache file                                        /*{{{*/
 // ---------------------------------------------------------------------
@@ -133,12 +144,12 @@ bool pkgCache::ReMap(bool const &Errorchecks)
    PkgP = (Package *)Map.Data();
    VerFileP = (VerFile *)Map.Data();
    DescFileP = (DescFile *)Map.Data();
+   RlsFileP = (ReleaseFile *)Map.Data();
    PkgFileP = (PackageFile *)Map.Data();
    VerP = (Version *)Map.Data();
    DescP = (Description *)Map.Data();
    ProvideP = (Provides *)Map.Data();
    DepP = (Dependency *)Map.Data();
-   StringItemP = (StringItem *)Map.Data();
    StrP = (char *)Map.Data();
 
    if (Errorchecks == false)
@@ -161,15 +172,23 @@ bool pkgCache::ReMap(bool const &Errorchecks)
    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"));
+
    // Locate our VS..
-   if (HeaderP->VerSysName == 0 ||
-       (VS = pkgVersioningSystem::GetVS(StrP + HeaderP->VerSysName)) == 0)
+   if ((VS = pkgVersioningSystem::GetVS(StrP + HeaderP->VerSysName)) == 0)
       return _error->Error(_("This APT does not support the versioning system '%s'"),StrP + HeaderP->VerSysName);
 
-   // Chcek the arhcitecture
-   if (HeaderP->Architecture == 0 ||
-       _config->Find("APT::Architecture") != StrP + HeaderP->Architecture)
-      return _error->Error(_("The package cache was built for a different architecture"));
+   // Check the architecture
+   std::vector<std::string> archs = APT::Configuration::getArchitectures();
+   std::vector<std::string>::const_iterator a = archs.begin();
+   std::string list = *a;
+   for (++a; a != archs.end(); ++a)
+      list.append(",").append(*a);
+   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());
+
    return true;
 }
                                                                        /*}}}*/
@@ -178,20 +197,20 @@ 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) */
-unsigned long pkgCache::sHash(const string &Str) const
+map_id_t pkgCache::sHash(const string &Str) const
 {
    unsigned long Hash = 0;
    for (string::const_iterator I = Str.begin(); I != Str.end(); ++I)
       Hash = 41 * Hash + tolower_ascii(*I);
-   return Hash % _count(HeaderP->PkgHashTable);
+   return Hash % HeaderP->GetHashTableSize();
 }
 
-unsigned long pkgCache::sHash(const char *Str) const
+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);
-   return Hash % _count(HeaderP->PkgHashTable);
+   return Hash % HeaderP->GetHashTableSize();
 }
                                                                        /*}}}*/
 // Cache::SingleArchFindPkg - Locate a package by name                 /*{{{*/
@@ -202,13 +221,10 @@ unsigned long pkgCache::sHash(const char *Str) const
 pkgCache::PkgIterator pkgCache::SingleArchFindPkg(const string &Name)
 {
    // Look at the hash bucket
-   Package *Pkg = PkgP + HeaderP->PkgHashTable[Hash(Name)];
+   Package *Pkg = PkgP + HeaderP->PkgHashTableP()[Hash(Name)];
    for (; Pkg != PkgP; Pkg = PkgP + Pkg->NextPackage)
    {
-      if (unlikely(Pkg->Name == 0))
-        continue;
-
-      int const cmp = strcasecmp(Name.c_str(), StrP + Pkg->Name);
+      int const cmp = strcmp(Name.c_str(), StrP + (GrpP + Pkg->Group)->Name);
       if (cmp == 0)
         return PkgIterator(*this, Pkg);
       else if (cmp < 0)
@@ -223,12 +239,7 @@ pkgCache::PkgIterator pkgCache::SingleArchFindPkg(const string &Name)
 pkgCache::PkgIterator pkgCache::FindPkg(const string &Name) {
        size_t const found = Name.find(':');
        if (found == string::npos)
-       {
-               if (MultiArchCache() == false)
-                       return SingleArchFindPkg(Name);
-               else
-                       return FindPkg(Name, "native");
-       }
+          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.
@@ -242,13 +253,6 @@ 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) {
-       if (MultiArchCache() == false && Arch != "none") {
-               if (Arch == "native" || Arch == "all" || Arch == "any" ||
-                   Arch == NativeArch())
-                       return SingleArchFindPkg(Name);
-               else
-                       return PkgIterator(*this,0);
-       }
        /* 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) */
@@ -267,12 +271,9 @@ pkgCache::GrpIterator pkgCache::FindGrp(const string &Name) {
                return GrpIterator(*this,0);
 
        // Look at the hash bucket for the group
-       Group *Grp = GrpP + HeaderP->GrpHashTable[sHash(Name)];
+       Group *Grp = GrpP + HeaderP->GrpHashTableP()[sHash(Name)];
        for (; Grp != GrpP; Grp = GrpP + Grp->Next) {
-               if (unlikely(Grp->Name == 0))
-                  continue;
-
-               int const cmp = strcasecmp(Name.c_str(), StrP + Grp->Name);
+               int const cmp = strcmp(Name.c_str(), StrP + Grp->Name);
                if (cmp == 0)
                        return GrpIterator(*this, Grp);
                else if (cmp < 0)
@@ -349,19 +350,15 @@ pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) const {
           last one we check, so we do it now. */
        if (Arch == "native" || Arch == myArch || Arch == "all") {
                pkgCache::Package *Pkg = Owner->PkgP + S->LastPackage;
-               if (strcasecmp(myArch, Owner->StrP + Pkg->Arch) == 0)
+               if (strcmp(myArch, Owner->StrP + Pkg->Arch) == 0)
                        return PkgIterator(*Owner, Pkg);
                Arch = myArch;
        }
 
-       /* Iterate over the list to find the matching arch
-          unfortunately this list includes "package noise"
-          (= different packages with same calculated hash),
-          so we need to check the name also */
+       // Iterate over the list to find the matching arch
        for (pkgCache::Package *Pkg = PackageList(); Pkg != Owner->PkgP;
             Pkg = Owner->PkgP + Pkg->NextPackage) {
-               if (S->Name == Pkg->Name &&
-                   stringcasecmp(Arch, Owner->StrP + Pkg->Arch) == 0)
+               if (stringcmp(Arch, Owner->StrP + Pkg->Arch) == 0)
                        return PkgIterator(*Owner, Pkg);
                if ((Owner->PkgP + S->LastPackage) == Pkg)
                        break;
@@ -414,36 +411,36 @@ pkgCache::PkgIterator pkgCache::GrpIterator::NextPkg(pkgCache::PkgIterator const
 // GrpIterator::operator ++ - Postfix incr                             /*{{{*/
 // ---------------------------------------------------------------------
 /* This will advance to the next logical group in the hash table. */
-void pkgCache::GrpIterator::operator ++(int) 
+void pkgCache::GrpIterator::operator ++(int)
 {
    // Follow the current links
    if (S != Owner->GrpP)
       S = Owner->GrpP + S->Next;
 
    // Follow the hash table
-   while (S == Owner->GrpP && (HashIndex+1) < (signed)_count(Owner->HeaderP->GrpHashTable))
+   while (S == Owner->GrpP && (HashIndex+1) < (signed)Owner->HeaderP->GetHashTableSize())
    {
       HashIndex++;
-      S = Owner->GrpP + Owner->HeaderP->GrpHashTable[HashIndex];
+      S = Owner->GrpP + Owner->HeaderP->GrpHashTableP()[HashIndex];
    }
-};
+}
                                                                        /*}}}*/
 // PkgIterator::operator ++ - Postfix incr                             /*{{{*/
 // ---------------------------------------------------------------------
 /* This will advance to the next logical package in the hash table. */
-void pkgCache::PkgIterator::operator ++(int) 
+void pkgCache::PkgIterator::operator ++(int)
 {
    // Follow the current links
    if (S != Owner->PkgP)
       S = Owner->PkgP + S->NextPackage;
 
    // Follow the hash table
-   while (S == Owner->PkgP && (HashIndex+1) < (signed)_count(Owner->HeaderP->PkgHashTable))
+   while (S == Owner->PkgP && (HashIndex+1) < (signed)Owner->HeaderP->GetHashTableSize())
    {
       HashIndex++;
-      S = Owner->PkgP + Owner->HeaderP->PkgHashTable[HashIndex];
+      S = Owner->PkgP + Owner->HeaderP->PkgHashTableP()[HashIndex];
    }
-};
+}
                                                                        /*}}}*/
 // PkgIterator::State - Check the State of the package                 /*{{{*/
 // ---------------------------------------------------------------------
@@ -475,26 +472,26 @@ pkgCache::PkgIterator::OkState pkgCache::PkgIterator::State() const
 // ---------------------------------------------------------------------
 /* Return string representing of the candidate version. */
 const char *
-pkgCache::PkgIterator::CandVersion() const 
+pkgCache::PkgIterator::CandVersion() const
 {
   //TargetVer is empty, so don't use it.
   VerIterator version = pkgPolicy(Owner).GetCandidateVer(*this);
   if (version.IsGood())
     return version.VerStr();
   return 0;
-};
+}
                                                                        /*}}}*/
 // PkgIterator::CurVersion - Returns the current version string                /*{{{*/
 // ---------------------------------------------------------------------
 /* Return string representing of the current version. */
 const char *
-pkgCache::PkgIterator::CurVersion() const 
+pkgCache::PkgIterator::CurVersion() const
 {
   VerIterator version = CurrentVer();
   if (version.IsGood())
     return CurrentVer().VerStr();
   return 0;
-};
+}
                                                                        /*}}}*/
 // ostream operator to handle string representation of a package       /*{{{*/
 // ---------------------------------------------------------------------
@@ -517,7 +514,10 @@ operator<<(std::ostream& out, pkgCache::PkgIterator Pkg)
       out << " -> " << candidate;
    if ( newest != "none" && candidate != newest)
       out << " | " << newest;
-   out << " > ( " << string(Pkg.Section()==0?"none":Pkg.Section()) << " )";
+   if (Pkg->VersionList == 0)
+      out << " > ( none )";
+   else
+      out << " > ( " << string(Pkg.VersionList().Section()==0?"unknown":Pkg.VersionList().Section()) << " )";
    return out;
 }
                                                                        /*}}}*/
@@ -695,7 +695,7 @@ void pkgCache::DepIterator::GlobOr(DepIterator &Start,DepIterator &End)
 // ---------------------------------------------------------------------
 /* Deps like self-conflicts should be ignored as well as implicit conflicts
    on virtual packages. */
-bool pkgCache::DepIterator::IsIgnorable(PkgIterator const &Pkg) const
+bool pkgCache::DepIterator::IsIgnorable(PkgIterator const &/*Pkg*/) const
 {
    if (IsNegative() == false)
       return false;
@@ -815,11 +815,11 @@ int pkgCache::VerIterator::CompareVer(const VerIterator &B) const
 // VerIterator::Downloadable - Checks if the version is downloadable   /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-bool pkgCache::VerIterator::Downloadable() const
+APT_PURE bool pkgCache::VerIterator::Downloadable() const
 {
    VerFileIterator Files = FileList();
    for (; Files.end() == false; ++Files)
-      if ((Files.File()->Flags & pkgCache::Flag::NotSource) != pkgCache::Flag::NotSource)
+      if (Files.File().Flagged(pkgCache::Flag::NotSource) == false)
         return true;
    return false;
 }
@@ -828,12 +828,12 @@ bool pkgCache::VerIterator::Downloadable() const
 // ---------------------------------------------------------------------
 /* This checks to see if any of the versions files are not NotAutomatic. 
    True if this version is selectable for automatic installation. */
-bool pkgCache::VerIterator::Automatic() const
+APT_PURE bool pkgCache::VerIterator::Automatic() const
 {
    VerFileIterator Files = FileList();
    for (; Files.end() == false; ++Files)
       // Do not check ButAutomaticUpgrades here as it is kind of automatic…
-      if ((Files.File()->Flags & pkgCache::Flag::NotAutomatic) != pkgCache::Flag::NotAutomatic)
+      if (Files.File().Flagged(pkgCache::Flag::NotAutomatic) == false)
         return true;
    return false;
 }
@@ -866,27 +866,27 @@ string pkgCache::VerIterator::RelStr() const
    for (pkgCache::VerFileIterator I = this->FileList(); I.end() == false; ++I)
    {
       // Do not print 'not source' entries'
-      pkgCache::PkgFileIterator File = I.File();
-      if ((File->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource)
+      pkgCache::PkgFileIterator const File = I.File();
+      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 File2 = J.File();
-        if (File2->Label == 0 || File->Label == 0)
+        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)
+        if (File2.Version() == File.Version())
         {
            Seen = true;
            break;
         }
-        if (File2->Version == 0 || File->Version == 0)
+        if (File2.Version() == 0 || File.Version() == 0)
            break;
         if (strcmp(File.Version(),File2.Version()) == 0)
            Seen = true;
@@ -900,12 +900,12 @@ string pkgCache::VerIterator::RelStr() const
       else
         First = false;
       
-      if (File->Label != 0)
+      if (File.Label() != 0)
         Res = Res + File.Label() + ':';
 
-      if (File->Archive != 0)
+      if (File.Archive() != 0)
       {
-        if (File->Version == 0)
+        if (File.Version() == 0)
            Res += File.Archive();
         else
            Res = Res + File.Version() + '/' +  File.Archive();
@@ -913,7 +913,7 @@ string pkgCache::VerIterator::RelStr() const
       else
       {
         // No release file, print the host name that this came from
-        if (File->Site == 0 || File.Site()[0] == 0)
+        if (File.Site() == 0 || File.Site()[0] == 0)
            Res += "localhost";
         else
            Res += File.Site();
@@ -936,12 +936,12 @@ const char * pkgCache::VerIterator::MultiArchType() const
    return "none";
 }
                                                                        /*}}}*/
-// PkgFileIterator::IsOk - Checks if the cache is in sync with the file        /*{{{*/
+// RlsFileIterator::IsOk - Checks if the cache is in sync with the file        /*{{{*/
 // ---------------------------------------------------------------------
 /* This stats the file and compares its stats with the ones that were
-   stored during generation. Date checks should probably also be 
+   stored during generation. Date checks should probably also be
    included here. */
-bool pkgCache::PkgFileIterator::IsOk()
+bool pkgCache::RlsFileIterator::IsOk()
 {
    struct stat Buf;
    if (stat(FileName(),&Buf) != 0)
@@ -953,10 +953,8 @@ bool pkgCache::PkgFileIterator::IsOk()
    return true;
 }
                                                                        /*}}}*/
-// PkgFileIterator::RelStr - Return the release string                 /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-string pkgCache::PkgFileIterator::RelStr()
+// RlsFileIterator::RelStr - Return the release string                 /*{{{*/
+string pkgCache::RlsFileIterator::RelStr()
 {
    string Res;
    if (Version() != 0)
@@ -969,8 +967,40 @@ string pkgCache::PkgFileIterator::RelStr()
       Res = Res + (Res.empty() == true?"n=":",n=")  + Codename();
    if (Label() != 0)
       Res = Res + (Res.empty() == true?"l=":",l=")  + Label();
-   if (Component() != 0)
-      Res = Res + (Res.empty() == true?"c=":",c=")  + Component();
+   return Res;
+}
+                                                                       /*}}}*/
+// PkgFileIterator::IsOk - Checks if the cache is in sync with the file        /*{{{*/
+// ---------------------------------------------------------------------
+/* This stats the file and compares its stats with the ones that were
+   stored during generation. Date checks should probably also be
+   included here. */
+bool pkgCache::PkgFileIterator::IsOk()
+{
+   struct stat Buf;
+   if (stat(FileName(),&Buf) != 0)
+      return false;
+
+   if (Buf.st_size != (signed)S->Size || Buf.st_mtime != S->mtime)
+      return false;
+
+   return true;
+}
+                                                                       /*}}}*/
+string pkgCache::PkgFileIterator::RelStr()                             /*{{{*/
+{
+   std::string Res;
+   if (ReleaseFile() == 0)
+   {
+      if (Component() != 0)
+        Res = Res + (Res.empty() == true?"a=":",a=")  + Component();
+   }
+   else
+   {
+      Res = ReleaseFile().RelStr();
+      if (Component() != 0)
+        Res = Res + (Res.empty() == true?"c=":",c=")  + Component();
+   }
    if (Architecture() != 0)
       Res = Res + (Res.empty() == true?"b=":",b=")  + Architecture();
    return Res;
@@ -978,7 +1008,7 @@ string pkgCache::PkgFileIterator::RelStr()
                                                                        /*}}}*/
 // VerIterator::TranslatedDescription - Return the a DescIter for locale/*{{{*/
 // ---------------------------------------------------------------------
-/* return a DescIter for the current locale or the default if none is 
+/* return a DescIter for the current locale or the default if none is
  * found
  */
 pkgCache::DescIterator pkgCache::VerIterator::TranslatedDescription() const
@@ -1012,7 +1042,7 @@ pkgCache::DescIterator pkgCache::VerIterator::TranslatedDescription() const
       if (strcmp(Desc.LanguageCode(), "") == 0)
         return Desc;
    return DescriptionList();
-};
+}
 
                                                                        /*}}}*/
 // PrvIterator::IsMultiArchImplicit - added by the cache generation    /*{{{*/
@@ -1024,8 +1054,10 @@ bool pkgCache::PrvIterator::IsMultiArchImplicit() const
 {
    pkgCache::PkgIterator const Owner = OwnerPkg();
    pkgCache::PkgIterator const Parent = ParentPkg();
-   if (strcmp(Owner.Arch(), Parent.Arch()) != 0 || Owner->Name == Parent->Name)
+   if (strcmp(Owner.Arch(), Parent.Arch()) != 0 || Owner.Group()->Name == Parent.Group()->Name)
       return true;
    return false;
 }
                                                                        /*}}}*/
+
+pkgCache::~pkgCache() {}