]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/tagfile.cc
Avoid wedging the entire system if recoverable :/.
[apt.git] / apt-pkg / tagfile.cc
index 3a3a3a04a5895044cc27f793d461ba07bc790446..72dd475b363a9d81a85e5c80ce727f273ddaaf58 100644 (file)
@@ -14,6 +14,7 @@
 #include<config.h>
 
 #include <apt-pkg/tagfile.h>
+#include <apt-pkg/tagfile-keys.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/fileutl.h>
@@ -98,7 +99,7 @@ public:
 };
                                                                        /*}}}*/
 
-static unsigned long AlphaHash(const char *Text, size_t Length)                /*{{{*/
+static unsigned long BetaHash(const char *Text, size_t Length)         /*{{{*/
 {
    /* This very simple hash function for the last 8 letters gives
       very good performance on the debian package files */
@@ -110,7 +111,7 @@ static unsigned long AlphaHash(const char *Text, size_t Length)             /*{{{*/
    unsigned long Res = 0;
    for (size_t i = 0; i < Length; ++i)
       Res = ((unsigned long)(Text[i]) & 0xDF) ^ (Res << 1);
-   return Res & 0xFF;
+   return Res & 0x7F;
 }
                                                                        /*}}}*/
 
@@ -214,7 +215,7 @@ bool pkgTagFile::Step(pkgTagSection &Tag)
            break;
 
         if (Resize() == false)
-           return _error->Error(_("Unable to parse package file %s (%d)"),
+           return _error->Warning(_("Unable to parse package file %s (%d)"),
                  d->Fd->Name().c_str(), 1);
 
       } while (Tag.Scan(d->Start,d->End - d->Start, false) == false);
@@ -300,7 +301,7 @@ static void RemoveCommentsFromBuffer(pkgTagFilePrivate * const d)
    std::vector<std::pair<char*, size_t>> good_parts;
    while (current <= d->End)
    {
-      size_t const restLength = (d->End - current) + 1;
+      size_t const restLength = (d->End - current);
       if (d->isCommentedLine == false)
       {
         current = static_cast<char*>(memchr(current, '#', restLength));
@@ -335,7 +336,7 @@ static void RemoveCommentsFromBuffer(pkgTagFilePrivate * const d)
         }
         ++current;
         // is the next line a comment, too?
-        if (current > d->End || *current != '#')
+        if (current >= d->End || *current != '#')
         {
            d->chunks.emplace_back(false, (current - bad_start));
            good_start = current;
@@ -474,6 +475,7 @@ pkgTagSection::pkgTagSection()
    : Section(0), d(new pkgTagSectionPrivate()), Stop(0)
 {
    memset(&AlphaIndexes, 0, sizeof(AlphaIndexes));
+   memset(&BetaIndexes, 0, sizeof(BetaIndexes));
 }
 APT_IGNORE_DEPRECATED_POP
                                                                        /*}}}*/
@@ -499,6 +501,7 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const R
       if (d->Tags.empty() == false)
       {
         memset(&AlphaIndexes, 0, sizeof(AlphaIndexes));
+        memset(&BetaIndexes, 0, sizeof(BetaIndexes));
         d->Tags.clear();
       }
       d->Tags.reserve(0x100);
@@ -510,7 +513,8 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const R
 
    pkgTagSectionPrivate::TagData lastTagData(0);
    lastTagData.EndTag = 0;
-   unsigned long lastTagHash = 0;
+   Key lastTagKey = Key::Unknown;
+   unsigned int lastTagHash = 0;
    while (Stop < End)
    {
       TrimRecord(true,End);
@@ -526,11 +530,15 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const R
         // store the last found tag
         if (lastTagData.EndTag != 0)
         {
-           if (AlphaIndexes[lastTagHash] != 0)
-              lastTagData.NextInBucket = AlphaIndexes[lastTagHash];
-           APT_IGNORE_DEPRECATED_PUSH
-           AlphaIndexes[lastTagHash] = TagCount;
-           APT_IGNORE_DEPRECATED_POP
+           if (lastTagKey != Key::Unknown) {
+              AlphaIndexes[static_cast<size_t>(lastTagKey)] = TagCount;
+           } else {
+              if (BetaIndexes[lastTagHash] != 0)
+                 lastTagData.NextInBucket = BetaIndexes[lastTagHash];
+              APT_IGNORE_DEPRECATED_PUSH
+              BetaIndexes[lastTagHash] = TagCount;
+              APT_IGNORE_DEPRECATED_POP
+           }
            d->Tags.push_back(lastTagData);
         }
 
@@ -547,7 +555,9 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const R
            ;
         ++EndTag;
         lastTagData.EndTag = EndTag - Section;
-        lastTagHash = AlphaHash(Stop, EndTag - Stop);
+        lastTagKey = pkgTagHash(Stop, EndTag - Stop);
+        if (lastTagKey == Key::Unknown)
+           lastTagHash = BetaHash(Stop, EndTag - Stop);
         // find the beginning of the value
         Stop = Colon + 1;
         for (; Stop < End && isspace_ascii(*Stop) != 0; ++Stop)
@@ -572,9 +582,13 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const R
       {
         if (lastTagData.EndTag != 0)
         {
-           if (AlphaIndexes[lastTagHash] != 0)
-              lastTagData.NextInBucket = AlphaIndexes[lastTagHash];
-           APT_IGNORE_DEPRECATED(AlphaIndexes[lastTagHash] = TagCount;)
+           if (lastTagKey != Key::Unknown) {
+              AlphaIndexes[static_cast<size_t>(lastTagKey)] = TagCount;
+           } else {
+              if (BetaIndexes[lastTagHash] != 0)
+                 lastTagData.NextInBucket = BetaIndexes[lastTagHash];
+              APT_IGNORE_DEPRECATED(BetaIndexes[lastTagHash] = TagCount;)
+           }
            d->Tags.push_back(lastTagData);
         }
 
@@ -618,11 +632,21 @@ bool pkgTagSection::Exists(StringView Tag) const
 // TagSection::Find - Locate a tag                                     /*{{{*/
 // ---------------------------------------------------------------------
 /* This searches the section for a tag that matches the given string. */
+bool pkgTagSection::Find(Key key,unsigned int &Pos) const
+{
+   auto Bucket = AlphaIndexes[static_cast<size_t>(key)];
+   Pos = Bucket - 1;
+   return Bucket != 0;
+}
 bool pkgTagSection::Find(StringView TagView,unsigned int &Pos) const
 {
    const char * const Tag = TagView.data();
    size_t const Length = TagView.length();
-   unsigned int Bucket = AlphaIndexes[AlphaHash(Tag, Length)];
+   auto key = pkgTagHash(Tag, Length);
+   if (key != Key::Unknown)
+      return Find(key, Pos);
+
+   unsigned int Bucket = BetaIndexes[BetaHash(Tag, Length)];
    if (Bucket == 0)
       return false;
 
@@ -643,13 +667,9 @@ bool pkgTagSection::Find(StringView TagView,unsigned int &Pos) const
    return false;
 }
 
-bool pkgTagSection::Find(StringView Tag,const char *&Start,
+bool pkgTagSection::FindInternal(unsigned int Pos, const char *&Start,
                         const char *&End) const
 {
-   unsigned int Pos;
-   if (Find(Tag, Pos) == false)
-      return false;
-
    Start = Section + d->Tags[Pos].StartValue;
    // Strip off the gunk from the end
    End = Section + d->Tags[Pos + 1].StartTag;
@@ -659,6 +679,18 @@ bool pkgTagSection::Find(StringView Tag,const char *&Start,
    for (; isspace_ascii(End[-1]) != 0 && End > Start; --End);
 
    return true;
+}
+bool pkgTagSection::Find(StringView Tag,const char *&Start,
+                        const char *&End) const
+{
+   unsigned int Pos;
+   return Find(Tag, Pos) && FindInternal(Pos, Start, End);
+}
+bool pkgTagSection::Find(Key key,const char *&Start,
+                        const char *&End) const
+{
+   unsigned int Pos;
+   return Find(key, Pos) && FindInternal(Pos, Start, End);
 }
                                                                        /*}}}*/
 // TagSection::FindS - Find a string                                   /*{{{*/
@@ -669,15 +701,19 @@ StringView pkgTagSection::Find(StringView Tag) const
    if (Find(Tag,Start,End) == false)
       return StringView();
    return StringView(Start, End - Start);
+}
+StringView pkgTagSection::Find(Key key) const
+{
+   const char *Start;
+   const char *End;
+   if (Find(key,Start,End) == false)
+      return StringView();
+   return StringView(Start, End - Start);
 }
                                                                        /*}}}*/
 // TagSection::FindRawS - Find a string                                        /*{{{*/
-StringView pkgTagSection::FindRaw(StringView Tag) const
+StringView pkgTagSection::FindRawInternal(unsigned int Pos) const
 {
-   unsigned int Pos;
-   if (Find(Tag, Pos) == false)
-      return "";
-
    char const *Start = (char const *) memchr(Section + d->Tags[Pos].EndTag, ':', d->Tags[Pos].StartValue - d->Tags[Pos].EndTag);
    ++Start;
    char const *End = Section + d->Tags[Pos + 1].StartTag;
@@ -687,16 +723,26 @@ StringView pkgTagSection::FindRaw(StringView Tag) const
    for (; isspace_ascii(End[-1]) != 0 && End > Start; --End);
 
    return StringView(Start, End - Start);
+}
+StringView pkgTagSection::FindRaw(StringView Tag) const
+{
+   unsigned int Pos;
+   return Find(Tag, Pos) ? FindRawInternal(Pos) : "";
+}
+StringView pkgTagSection::FindRaw(Key key) const
+{
+   unsigned int Pos;
+   return Find(key, Pos) ? FindRawInternal(Pos) : "";
 }
                                                                        /*}}}*/
 // TagSection::FindI - Find an integer                                 /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-signed int pkgTagSection::FindI(StringView Tag,signed long Default) const
+signed int pkgTagSection::FindIInternal(unsigned int Pos,signed long Default) const
 {
    const char *Start;
    const char *Stop;
-   if (Find(Tag,Start,Stop) == false)
+   if (FindInternal(Pos,Start,Stop) == false)
       return Default;
 
    // Copy it into a temp buffer so we can use strtol
@@ -717,16 +763,28 @@ signed int pkgTagSection::FindI(StringView Tag,signed long Default) const
    if (S == End)
       return Default;
    return Result;
+}
+signed int pkgTagSection::FindI(Key key,signed long Default) const
+{
+   unsigned int Pos;
+
+   return Find(key, Pos) ? FindIInternal(Pos) : Default;
+}
+signed int pkgTagSection::FindI(StringView Tag,signed long Default) const
+{
+   unsigned int Pos;
+
+   return Find(Tag, Pos) ? FindIInternal(Pos, Default) : Default;
 }
                                                                        /*}}}*/
 // TagSection::FindULL - Find an unsigned long long integer            /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-unsigned long long pkgTagSection::FindULL(StringView Tag, unsigned long long const &Default) const
+unsigned long long pkgTagSection::FindULLInternal(unsigned int Pos, unsigned long long const &Default) const
 {
    const char *Start;
    const char *Stop;
-   if (Find(Tag,Start,Stop) == false)
+   if (FindInternal(Pos,Start,Stop) == false)
       return Default;
 
    // Copy it into a temp buffer so we can use strtoull
@@ -741,31 +799,69 @@ unsigned long long pkgTagSection::FindULL(StringView Tag, unsigned long long con
    if (S == End)
       return Default;
    return Result;
+}
+unsigned long long pkgTagSection::FindULL(Key key, unsigned long long const &Default) const
+{
+   unsigned int Pos;
+
+   return Find(key, Pos) ? FindULLInternal(Pos, Default) : Default;
+}
+unsigned long long pkgTagSection::FindULL(StringView Tag, unsigned long long const &Default) const
+{
+   unsigned int Pos;
+
+   return Find(Tag, Pos) ? FindULLInternal(Pos, Default) : Default;
 }
                                                                        /*}}}*/
 // TagSection::FindB - Find boolean value                              /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-bool pkgTagSection::FindB(StringView Tag, bool Default) const
+bool pkgTagSection::FindBInternal(unsigned int Pos, bool Default) const
 {
    const char *Start, *Stop;
-   if (Find(Tag, Start, Stop) == false)
+   if (FindInternal(Pos, Start, Stop) == false)
       return Default;
    return StringToBool(string(Start, Stop));
+}
+bool pkgTagSection::FindB(Key key, bool Default) const
+{
+   unsigned int Pos;
+   return Find(key, Pos) ? FindBInternal(Pos, Default): Default;
+}
+bool pkgTagSection::FindB(StringView Tag, bool Default) const
+{
+   unsigned int Pos;
+   return Find(Tag, Pos) ? FindBInternal(Pos, Default) : Default;
 }
                                                                        /*}}}*/
 // TagSection::FindFlag - Locate a yes/no type flag                    /*{{{*/
 // ---------------------------------------------------------------------
 /* The bits marked in Flag are masked on/off in Flags */
-bool pkgTagSection::FindFlag(StringView Tag, uint8_t &Flags,
+bool pkgTagSection::FindFlagInternal(unsigned int Pos, uint8_t &Flags,
                             uint8_t const Flag) const
 {
    const char *Start;
    const char *Stop;
-   if (Find(Tag,Start,Stop) == false)
+   if (FindInternal(Pos,Start,Stop) == false)
       return true;
    return FindFlag(Flags, Flag, Start, Stop);
 }
+bool pkgTagSection::FindFlag(Key key, uint8_t &Flags,
+                            uint8_t const Flag) const
+{
+   unsigned int Pos;
+   if (Find(key,Pos) == false)
+      return true;
+   return FindFlagInternal(Pos, Flags, Flag);
+}
+bool pkgTagSection::FindFlag(StringView Tag, uint8_t &Flags,
+                            uint8_t const Flag) const
+{
+   unsigned int Pos;
+   if (Find(Tag,Pos) == false)
+      return true;
+   return FindFlagInternal(Pos, Flags, Flag);
+}
 bool pkgTagSection::FindFlag(uint8_t &Flags, uint8_t const Flag,
                                        char const* const Start, char const* const Stop)
 {
@@ -785,15 +881,27 @@ bool pkgTagSection::FindFlag(uint8_t &Flags, uint8_t const Flag,
    }
    return true;
 }
-bool pkgTagSection::FindFlag(StringView Tag,unsigned long &Flags,
+bool pkgTagSection::FindFlagInternal(unsigned int Pos,unsigned long &Flags,
                             unsigned long Flag) const
 {
    const char *Start;
    const char *Stop;
-   if (Find(Tag,Start,Stop) == false)
+   if (FindInternal(Pos,Start,Stop) == false)
       return true;
    return FindFlag(Flags, Flag, Start, Stop);
 }
+bool pkgTagSection::FindFlag(Key key,unsigned long &Flags,
+                            unsigned long Flag) const
+{
+   unsigned int Pos;
+   return Find(key, Pos) ? FindFlagInternal(Pos, Flags, Flag) : true;
+}
+bool pkgTagSection::FindFlag(StringView Tag,unsigned long &Flags,
+                            unsigned long Flag) const
+{
+   unsigned int Pos;
+   return Find(Tag, Pos) ? FindFlagInternal(Pos, Flags, Flag) : true;
+}
 bool pkgTagSection::FindFlag(unsigned long &Flags, unsigned long Flag,
                                        char const* Start, char const* Stop)
 {