diff options
author | Michael Vogt <michael.vogt@ubuntu.com> | 2006-08-09 14:45:01 +0200 |
---|---|---|
committer | Michael Vogt <michael.vogt@ubuntu.com> | 2006-08-09 14:45:01 +0200 |
commit | 754229c5d8e929a221645a5c56c1bd4274910c26 (patch) | |
tree | af29ab8694b0ff8876a2df83513c4cd41e492415 /apt-pkg/tagfile.cc | |
parent | af5a94f4c7b1f2cc797cd1e023e36a1bb359689d (diff) | |
parent | 1b5f30cb5575f274246b1dabad0efc7a7a549aac (diff) |
* merged with mainline
Diffstat (limited to 'apt-pkg/tagfile.cc')
-rw-r--r-- | apt-pkg/tagfile.cc | 115 |
1 files changed, 99 insertions, 16 deletions
diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc index 25e2930fa..8fcbeb23b 100644 --- a/apt-pkg/tagfile.cc +++ b/apt-pkg/tagfile.cc @@ -33,21 +33,32 @@ using std::string; /* */ pkgTagFile::pkgTagFile(FileFd *pFd,unsigned long Size) : Fd(*pFd), - Size(Size) + Size(Size), + Map(NULL), + Buffer(0) { - if (Fd.IsOpen() == false || Fd.Size() == 0) + if (Fd.IsOpen() == false) { - Buffer = 0; Start = End = Buffer = 0; + Done = true; iOffset = 0; Map = NULL; return; } - Map = new MMap (Fd, MMap::Public | MMap::ReadOnly); - Buffer = (char *) Map->Data (); - Start = Buffer; - End = Buffer + Map->Size (); + // check if we can MMap it + if(Fd.Size() == 0) + { + Buffer = new char[Size]; + Start = End = Buffer; + Done = false; + Fill(); + } else { + Map = new MMap (Fd, MMap::Public | MMap::ReadOnly); + Buffer = (char *) Map->Data (); + Start = Buffer; + End = Buffer + Map->Size (); + } iOffset = 0; } /*}}}*/ @@ -56,6 +67,7 @@ pkgTagFile::pkgTagFile(FileFd *pFd,unsigned long Size) : /* */ pkgTagFile::~pkgTagFile() { + if(!Map) delete [] Buffer; delete Map; } /*}}}*/ @@ -64,13 +76,21 @@ pkgTagFile::~pkgTagFile() /* If the Section Scanner fails we refill the buffer and try again. */ bool pkgTagFile::Step(pkgTagSection &Tag) { - if (Start == End) + if ((Map != NULL) && (Start == End)) return false; if (Tag.Scan(Start,End - Start) == false) { - return _error->Error(_("Unable to parse package file %s (1)"), - Fd.Name().c_str()); + if (Map != NULL) + return _error->Error(_("Unable to parse package file %s (1)"), + Fd.Name().c_str()); + + if (Fill() == false) + return false; + + if (Tag.Scan(Start,End - Start) == false) + return _error->Error(_("Unable to parse package file %s (1)"), + Fd.Name().c_str()); } Start += Tag.size(); iOffset += Tag.size(); @@ -79,6 +99,50 @@ bool pkgTagFile::Step(pkgTagSection &Tag) return true; } /*}}}*/ +// TagFile::Fill - Top up the buffer /*{{{*/ +// --------------------------------------------------------------------- +/* This takes the bit at the end of the buffer and puts it at the start + then fills the rest from the file */ +bool pkgTagFile::Fill() +{ + unsigned long EndSize = End - Start; + 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) + return false; + if (Actual != Size - (End - Buffer)) + Done = true; + End += Actual; + } + + if (Done == true) + { + if (EndSize <= 3 && Actual == 0) + return false; + if (Size - (End - Buffer) < 4) + 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; + } + + return true; +} + /*}}}*/ // TagFile::Jump - Jump to a pre-recorded location in the file /*{{{*/ // --------------------------------------------------------------------- /* This jumps to a pre-recorded file location and reads the record @@ -94,12 +158,31 @@ bool pkgTagFile::Jump(pkgTagSection &Tag,unsigned long Offset) return Step(Tag); } - // Reposition and reload.. iOffset = Offset; - Start = Buffer + iOffset; + if (Map != NULL) + { + Start = Buffer + iOffset; + } + else + { + // Reposition and reload.. + Done = false; + if (Fd.Seek(Offset) == false) + return false; + End = Start = Buffer; - // Start != End is a special case to not fail on empty TagFiles - if (Start != End && Tag.Scan(Start,End - Start) == false) + if (Fill() == false) + return false; + + if (Tag.Scan(Start,End - Start) == true) + return true; + + // This appends a double new line (for the real eof handling) + if (Fill() == false) + return false; + } + + if (Tag.Scan(Start,End - Start) == false) return _error->Error(_("Unable to parse package file %s (2)"),Fd.Name().c_str()); return true; @@ -157,8 +240,8 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength) if ((Stop+1 >= End) && (End[-1] == '\n' || End[-1] == '\r')) { - Indexes[TagCount] = (End - 1) - Section; - return true; + Indexes[TagCount] = (End - 1) - Section; + return true; } return false; |