[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#275852: parseTagFile: unable to cope with 'hurd-i386' architecture in sid Release files.



On Mon, May 16, 2005 at 04:20:28PM +0200, Christian Aichinger wrote:
> The patch is available in apt--export--0--patch-1.

Hi,
the archive is offline now, so I'm sending the patch here. It still
applies to apt in unstable.

Cheers,
Christian Aichinger
--- orig/apt-pkg/tagfile.cc
+++ mod/apt-pkg/tagfile.cc
@@ -80,48 +80,154 @@
    return true;
 }
 									/*}}}*/
-// TagFile::Fill - Top up the buffer					/*{{{*/
+// BuildCompleteBuffer - Build the real Buffer from its parts		/*{{{*/
 // ---------------------------------------------------------------------
-/* This takes the bit at the end of the buffer and puts it at the start
-   then fills the rest from the file */
+// (Utility function for TagFile::Fill()
+/* Copies all the data from [Start, End[, Buffers and Buf into a newly
+   allocated memory region that is returned in Result and ResultLen.
+   2 Bytes are guaranteed to be available at the end for a possible \n\n
+   */
+void BuildCompleteBuffer(
+	  char* StartBuf, unsigned long StartLen,
+	  const vector<char*> &Buffers, unsigned long BuffersLen,
+	  char* EndBuf, unsigned long EndLen,
+	  char** Result, unsigned long* ResultLen)
+{
+   unsigned long Needed = StartLen + Buffers.size()*BuffersLen + EndLen + 2;
+   char *Res = new char[Needed];
+   char *i = Res;
+
+
+   memcpy(i, StartBuf, StartLen);
+   i += StartLen;
+
+   for (vector<char*>::const_iterator BufIter = Buffers.begin();
+	 				BufIter != Buffers.end(); BufIter++) {
+      memcpy(i, *BufIter, BuffersLen);
+      i += BuffersLen;
+   }
+
+   memcpy(i, EndBuf, EndLen);
+   i += EndLen;
+
+   *Result = Res;
+   *ResultLen = i - Res;
+}
+									/*}}}*/
+// SearchDoubleNewline - Search for a \n[\r]*\n sequence		/*{{{*/
+// ---------------------------------------------------------------------
+// (Utility function for TagFile::Fill()
+/* Searches for a double-newline in [Start, End[ and returns true if it's found
+*/
+static bool SearchDoubleNewline(const void *Start, const void *End_)
+{
+   const char *NewLine = static_cast<const char *>(Start);
+   const char *End = static_cast<const char *>(End_);
+
+   while (1) {
+       NewLine = static_cast<const char *>(memchr(NewLine, '\n', End - NewLine));
+       if (!NewLine)
+           return false;
+
+       do { NewLine++; }
+       while ((NewLine < End) && (*NewLine == '\r'));
+
+       if (NewLine >= End)
+	  return false;
+
+       if (*NewLine == '\n')
+	  return true;
+   }
+}
+									/*}}}*/
+// AppendDoubleNewline - Appends a double-newline if necessary		/*{{{*/
+// ---------------------------------------------------------------------
+// (Utility function for TagFile::Fill()
+/* Looks if the buffer already ends in a double-Newline, and adds one if
+   necessary */
+static unsigned long AppendDoubleNewline(char *Start, char* End)
+{
+   // Append a double new line if one does not exist
+   unsigned int LineCount = 0;
+   for (const char *p = End - 1; (*p == '\n' || *p == '\r') && 
+	 			 (LineCount < 2) && (p > Start); p--) {
+      if (*p == '\n')
+	 LineCount++;
+   }
+   for (; LineCount < 2; LineCount++)
+      *End++ = '\n';
+
+   return End-Start;
+}
+									/*}}}*/
+// DeleteElements - Calls delete [] on all elements in the vector	/*{{{*/
+// ---------------------------------------------------------------------
+// delete[]s all elements in a Buffers vector passed to it.
+static inline void DeleteElements(vector<char*> Buffers) {
+   for (vector<char *>::iterator BufIter = Buffers.begin();
+	BufIter != Buffers.end();
+	BufIter++)
+      delete [] *BufIter;
+}
+									/*}}}*/
+// TagFile::Fill - Prepare Buffer for pkgTagSection.Scan()		/*{{{*/
+// ---------------------------------------------------------------------
+/* This function makes sure that a blank line is in the buffer, making it
+   useable for pkgTagSection.Scan(). If necessary data is read from the file. 
+   */
 bool pkgTagFile::Fill()
 {
-   unsigned long EndSize = End - Start;
+   if (SearchDoubleNewline(Start, End))
+      // we've found a double newline in the current buffer region, so we don't
+      // need to do anything.
+      return true;
+
+   if (Done)
+      // We're done, but SearchDoubleNewline didn't find a double NL in the
+      // current buffer space. So either something is going terribly wrong,
+      // or we're called at the EOF when all the data has been parsed
+      // already. Either way, there's nothing we can do.
+      return false;
+
+   vector<char*> Buffers;
    unsigned long Actual = 0;
-   
-   memmove(Buffer,Start,EndSize);
-   Start = Buffer;
-   End = Buffer + EndSize;
-   
-   if (Done == false)
-   {
-      // See if only a bit of the file is left
-      if (Fd.Read(End,Size - (End - Buffer),&Actual) == false)
+
+   // Load chunks from the file until we hit EOF or find a double-NL
+   while (true) {
+      char *NewBuf = new char[Size];
+
+      if (Fd.Read(NewBuf, Size, &Actual) == false) {
+	 delete [] NewBuf;
+	 DeleteElements(Buffers);
 	 return false;
-      if (Actual != Size - (End - Buffer))
+      }
+      if (Actual != Size)
 	 Done = true;
-      End += Actual;
-   }
-   
-   if (Done == true)
-   {
-      if (EndSize <= 3 && Actual == 0)
-	 return false;
-      if (Size - (End - Buffer) < 4)
+
+      if (Done || SearchDoubleNewline(NewBuf, NewBuf+Actual)) {
+	 char *Result;
+	 unsigned long ResultLen;
+	 // Create a new buffer, and copy all the accumulated data into it.
+	 BuildCompleteBuffer(Start, End-Start, Buffers, Size, NewBuf, Actual,
+	       &Result, &ResultLen);
+
+	 if (Done)
+	    ResultLen = AppendDoubleNewline(Result, Result+ResultLen);
+
+	 // Get rid of all the stuff we don't need anymore
+	 delete [] Buffer;
+	 delete [] NewBuf;
+	 DeleteElements(Buffers);
+
+	 Buffer = Result;
+	 Start = Result;
+	 End = Result+ResultLen;
+
 	 return true;
-      
-      // Append a double new line if one does not exist
-      unsigned int LineCount = 0;
-      for (const char *E = End - 1; E - End < 6 && (*E == '\n' || *E == '\r'); E--)
-	 if (*E == '\n')
-	    LineCount++;
-      for (; LineCount < 2; LineCount++)
-	 *End++ = '\n';
-      
-      return true;
+      }
+
+      Buffers.push_back(NewBuf);
    }
-   
-   return true;
 }
 									/*}}}*/
 // TagFile::Jump - Jump to a pre-recorded location in the file		/*{{{*/

Attachment: signature.asc
Description: Digital signature


Reply to: