summaryrefslogtreecommitdiff
path: root/apt-pkg
diff options
context:
space:
mode:
Diffstat (limited to 'apt-pkg')
-rw-r--r--apt-pkg/acquire-item.cc438
-rw-r--r--apt-pkg/acquire-item.h64
-rw-r--r--apt-pkg/acquire.cc8
-rw-r--r--apt-pkg/deb/debversion.cc23
-rw-r--r--apt-pkg/deb/dpkgpm.cc8
-rw-r--r--apt-pkg/tagfile.cc92
-rw-r--r--apt-pkg/tagfile.h5
7 files changed, 551 insertions, 87 deletions
diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc
index 1fa929aad..cc16215f5 100644
--- a/apt-pkg/acquire-item.cc
+++ b/apt-pkg/acquire-item.cc
@@ -24,6 +24,8 @@
#include <apt-pkg/strutl.h>
#include <apt-pkg/fileutl.h>
#include <apt-pkg/md5.h>
+#include <apt-pkg/sha1.h>
+#include <apt-pkg/tagfile.h>
#include <apti18n.h>
@@ -31,6 +33,7 @@
#include <unistd.h>
#include <errno.h>
#include <string>
+#include <sstream>
#include <stdio.h>
/*}}}*/
@@ -100,7 +103,8 @@ void pkgAcquire::Item::Done(string Message,unsigned long Size,string,
{
// We just downloaded something..
string FileName = LookupTag(Message,"Filename");
- if (Complete == false && FileName == DestFile)
+ // we only inform the Log class if it was actually not a local thing
+ if (Complete == false && !Local && FileName == DestFile)
{
if (Owner->Log != 0)
Owner->Log->Fetched(Size,atoi(LookupTag(Message,"Resume-Point","0").c_str()));
@@ -131,14 +135,431 @@ void pkgAcquire::Item::Rename(string From,string To)
}
/*}}}*/
+
+// AcqDiffIndex::AcqDiffIndex - Constructor
+// ---------------------------------------------------------------------
+/* Get the DiffIndex file first and see if there are patches availabe
+ * If so, create a pkgAcqIndexDiffs fetcher that will get and apply the
+ * patches. If anything goes wrong in that process, it will fall back to
+ * the original packages file
+ */
+pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner,
+ string URI,string URIDesc,string ShortDesc,
+ string ExpectedMD5)
+ : Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5), Description(URIDesc)
+{
+
+ Debug = _config->FindB("Debug::pkgAcquire::Diffs",false);
+
+ Desc.Description = URIDesc + "/DiffIndex";
+ Desc.Owner = this;
+ Desc.ShortDesc = ShortDesc;
+ Desc.URI = URI + ".diff/Index";
+
+ DestFile = _config->FindDir("Dir::State::lists") + "partial/";
+ DestFile += URItoFileName(URI) + string(".DiffIndex");
+
+ if(Debug)
+ std::clog << "pkgAcqDiffIndex: " << Desc.URI << std::endl;
+
+ // look for the current package file
+ CurrentPackagesFile = _config->FindDir("Dir::State::lists");
+ CurrentPackagesFile += URItoFileName(RealURI);
+
+ // FIXME: this file:/ check is a hack to prevent fetching
+ // from local sources. this is really silly, and
+ // should be fixed cleanly as soon as possible
+ if(!FileExists(CurrentPackagesFile) ||
+ Desc.URI.substr(0,strlen("file:/")) == "file:/")
+ {
+ // we don't have a pkg file or we don't want to queue
+ if(Debug)
+ std::clog << "No index file, local or canceld by user" << std::endl;
+ Failed("", NULL);
+ return;
+ }
+
+ if(Debug)
+ std::clog << "pkgAcqIndexDiffs::pkgAcqIndexDiffs(): "
+ << CurrentPackagesFile << std::endl;
+
+ QueueURI(Desc);
+
+}
+
+// AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/
+// ---------------------------------------------------------------------
+/* The only header we use is the last-modified header. */
+string pkgAcqDiffIndex::Custom600Headers()
+{
+ string Final = _config->FindDir("Dir::State::lists");
+ Final += URItoFileName(RealURI) + string(".IndexDiff");
+
+ if(Debug)
+ std::clog << "Custom600Header-IMS: " << Final << std::endl;
+
+ struct stat Buf;
+ if (stat(Final.c_str(),&Buf) != 0)
+ return "\nIndex-File: true";
+
+ return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
+}
+
+
+bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile)
+{
+ if(Debug)
+ std::clog << "pkgAcqIndexDiffs::ParseIndexDiff() " << IndexDiffFile
+ << std::endl;
+
+ pkgTagSection Tags;
+ string ServerSha1;
+ vector<DiffInfo> available_patches;
+
+ FileFd Fd(IndexDiffFile,FileFd::ReadOnly);
+ pkgTagFile TF(&Fd);
+ if (_error->PendingError() == true)
+ return false;
+
+ if(TF.Step(Tags) == true)
+ {
+ string local_sha1;
+ bool found = false;
+ DiffInfo d;
+ string size;
+
+ string tmp = Tags.FindS("SHA1-Current");
+ std::stringstream ss(tmp);
+ ss >> ServerSha1;
+
+ FileFd fd(CurrentPackagesFile, FileFd::ReadOnly);
+ SHA1Summation SHA1;
+ SHA1.AddFD(fd.Fd(), fd.Size());
+ local_sha1 = string(SHA1.Result());
+
+ if(local_sha1 == ServerSha1)
+ {
+ // we have the same sha1 as the server
+ if(Debug)
+ std::clog << "Package file is up-to-date" << std::endl;
+ // set found to true, this will queue a pkgAcqIndexDiffs with
+ // a empty availabe_patches
+ found = true;
+ }
+ else
+ {
+ if(Debug)
+ std::clog << "SHA1-Current: " << ServerSha1 << std::endl;
+
+ // check the historie and see what patches we need
+ string history = Tags.FindS("SHA1-History");
+ std::stringstream hist(history);
+ while(hist >> d.sha1 >> size >> d.file)
+ {
+ d.size = atoi(size.c_str());
+ // read until the first match is found
+ if(d.sha1 == local_sha1)
+ found=true;
+ // from that point on, we probably need all diffs
+ if(found)
+ {
+ if(Debug)
+ std::clog << "Need to get diff: " << d.file << std::endl;
+ available_patches.push_back(d);
+ }
+ }
+ }
+
+ // no information how to get the patches, bail out
+ if(!found)
+ {
+ if(Debug)
+ std::clog << "Can't find a patch in the index file" << std::endl;
+ // Failed will queue a big package file
+ Failed("", NULL);
+ }
+ else
+ {
+ // queue the diffs
+ new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc,
+ ExpectedMD5, available_patches);
+ Complete = false;
+ Status = StatDone;
+ Dequeue();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void pkgAcqDiffIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
+{
+ if(Debug)
+ std::clog << "pkgAcqDiffIndex failed: " << Desc.URI << std::endl
+ << "Falling back to normal index file aquire" << std::endl;
+
+ new pkgAcqIndex(Owner, RealURI, Description, Desc.ShortDesc,
+ ExpectedMD5);
+
+ Complete = false;
+ Status = StatDone;
+ Dequeue();
+}
+
+void pkgAcqDiffIndex::Done(string Message,unsigned long Size,string Md5Hash,
+ pkgAcquire::MethodConfig *Cnf)
+{
+ if(Debug)
+ std::clog << "pkgAcqDiffIndex::Done(): " << Desc.URI << std::endl;
+
+ Item::Done(Message,Size,Md5Hash,Cnf);
+
+ string FinalFile;
+ FinalFile = _config->FindDir("Dir::State::lists")+URItoFileName(RealURI);
+
+ // sucess in downloading the index
+ // rename the index
+ FinalFile += string(".IndexDiff");
+ if(Debug)
+ std::clog << "Renaming: " << DestFile << " -> " << FinalFile
+ << std::endl;
+ Rename(DestFile,FinalFile);
+ chmod(FinalFile.c_str(),0644);
+ DestFile = FinalFile;
+
+ if(!ParseDiffIndex(DestFile))
+ return Failed("", NULL);
+
+ Complete = true;
+ Status = StatDone;
+ Dequeue();
+ return;
+}
+
+
+
+// AcqIndexDiffs::AcqIndexDiffs - Constructor
+// ---------------------------------------------------------------------
+/* The package diff is added to the queue. one object is constructed
+ * for each diff and the index
+ */
+pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire *Owner,
+ string URI,string URIDesc,string ShortDesc,
+ string ExpectedMD5, vector<DiffInfo> diffs)
+ : Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5),
+ available_patches(diffs)
+{
+
+ DestFile = _config->FindDir("Dir::State::lists") + "partial/";
+ DestFile += URItoFileName(URI);
+
+ Debug = _config->FindB("Debug::pkgAcquire::Diffs",false);
+
+ Desc.Description = URIDesc;
+ Desc.Owner = this;
+ Desc.ShortDesc = ShortDesc;
+
+ if(available_patches.size() == 0)
+ {
+ // we are done (yeah!)
+ Finish(true);
+ }
+ else
+ {
+ // get the next diff
+ State = StateFetchDiff;
+ QueueNextDiff();
+ }
+}
+
+
+void pkgAcqIndexDiffs::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
+{
+ if(Debug)
+ std::clog << "pkgAcqIndexDiffs failed: " << Desc.URI << std::endl
+ << "Falling back to normal index file aquire" << std::endl;
+ new pkgAcqIndex(Owner, RealURI, Description,Desc.ShortDesc,
+ ExpectedMD5);
+ Finish();
+}
+
+
+// helper that cleans the item out of the fetcher queue
+void pkgAcqIndexDiffs::Finish(bool allDone)
+{
+ // we restore the original name, this is required, otherwise
+ // the file will be cleaned
+ if(allDone)
+ {
+ DestFile = _config->FindDir("Dir::State::lists");
+ DestFile += URItoFileName(RealURI);
+
+ // do the final md5sum checking
+ MD5Summation sum;
+ FileFd Fd(DestFile, FileFd::ReadOnly);
+ sum.AddFD(Fd.Fd(), Fd.Size());
+ Fd.Close();
+ string MD5 = (string)sum.Result();
+
+ if (!ExpectedMD5.empty() && MD5 != ExpectedMD5)
+ {
+ Status = StatAuthError;
+ ErrorText = _("MD5Sum mismatch");
+ Rename(DestFile,DestFile + ".FAILED");
+ Dequeue();
+ return;
+ }
+
+ // this is for the "real" finish
+ Complete = true;
+ Status = StatDone;
+ Dequeue();
+ if(Debug)
+ std::clog << "\n\nallDone: " << DestFile << "\n" << std::endl;
+ return;
+ }
+
+ if(Debug)
+ std::clog << "Finishing: " << Desc.URI << std::endl;
+ Complete = false;
+ Status = StatDone;
+ Dequeue();
+ return;
+}
+
+
+
+bool pkgAcqIndexDiffs::QueueNextDiff()
+{
+
+ // calc sha1 of the just patched file
+ string FinalFile = _config->FindDir("Dir::State::lists");
+ FinalFile += URItoFileName(RealURI);
+
+ FileFd fd(FinalFile, FileFd::ReadOnly);
+ SHA1Summation SHA1;
+ SHA1.AddFD(fd.Fd(), fd.Size());
+ string local_sha1 = string(SHA1.Result());
+ if(Debug)
+ std::clog << "QueueNextDiff: "
+ << FinalFile << " (" << local_sha1 << ")"<<std::endl;
+
+ // remove all patches until the next matching patch is found
+ // this requires the Index file to be ordered
+ for(vector<DiffInfo>::iterator I=available_patches.begin();
+ available_patches.size() > 0 &&
+ I != available_patches.end() &&
+ (*I).sha1 != local_sha1;
+ I++)
+ {
+ available_patches.erase(I);
+ }
+
+ // error checking and falling back if no patch was found
+ if(available_patches.size() == 0)
+ {
+ Failed("", NULL);
+ return false;
+ }
+
+ // queue the right diff
+ Desc.URI = string(RealURI) + ".diff/" + available_patches[0].file + ".gz";
+ Desc.Description = available_patches[0].file + string(".pdiff");
+
+ DestFile = _config->FindDir("Dir::State::lists") + "partial/";
+ DestFile += URItoFileName(RealURI + ".diff/" + available_patches[0].file);
+
+ if(Debug)
+ std::clog << "pkgAcqIndexDiffs::QueueNextDiff(): " << Desc.URI << std::endl;
+
+ QueueURI(Desc);
+
+ return true;
+}
+
+
+
+void pkgAcqIndexDiffs::Done(string Message,unsigned long Size,string Md5Hash,
+ pkgAcquire::MethodConfig *Cnf)
+{
+ if(Debug)
+ std::clog << "pkgAcqIndexDiffs::Done(): " << Desc.URI << std::endl;
+
+ Item::Done(Message,Size,Md5Hash,Cnf);
+
+ string FinalFile;
+ FinalFile = _config->FindDir("Dir::State::lists")+URItoFileName(RealURI);
+
+ // sucess in downloading a diff, enter ApplyDiff state
+ if(State == StateFetchDiff)
+ {
+
+ if(Debug)
+ std::clog << "Sending to gzip method: " << FinalFile << std::endl;
+
+ string FileName = LookupTag(Message,"Filename");
+ State = StateUnzipDiff;
+ Local = true;
+ Desc.URI = "gzip:" + FileName;
+ DestFile += ".decomp";
+ QueueURI(Desc);
+ Mode = "gzip";
+ return;
+ }
+
+ // sucess in downloading a diff, enter ApplyDiff state
+ if(State == StateUnzipDiff)
+ {
+
+ // rred excepts the patch as $FinalFile.ed
+ Rename(DestFile,FinalFile+".ed");
+
+ if(Debug)
+ std::clog << "Sending to rred method: " << FinalFile << std::endl;
+
+ State = StateApplyDiff;
+ Local = true;
+ Desc.URI = "rred:" + FinalFile;
+ QueueURI(Desc);
+ Mode = "rred";
+ return;
+ }
+
+
+ // success in download/apply a diff, queue next (if needed)
+ if(State == StateApplyDiff)
+ {
+ // remove the just applied patch
+ available_patches.erase(available_patches.begin());
+
+ // move into place
+ if(Debug)
+ {
+ std::clog << "Moving patched file in place: " << std::endl
+ << DestFile << " -> " << FinalFile << std::endl;
+ }
+ Rename(DestFile,FinalFile);
+
+ // see if there is more to download
+ if(available_patches.size() > 0) {
+ new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc,
+ ExpectedMD5, available_patches);
+ return Finish();
+ } else
+ return Finish(true);
+ }
+}
+
+
// AcqIndex::AcqIndex - Constructor /*{{{*/
// ---------------------------------------------------------------------
/* The package file is added to the queue and a second class is
instantiated to fetch the revision file */
pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner,
string URI,string URIDesc,string ShortDesc,
- string ExpectedMD5, string comprExt) :
- Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5)
+ string ExpectedMD5, string comprExt)
+ : Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5)
{
Decompression = false;
Erase = false;
@@ -601,9 +1022,14 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify)
}
}
- // Queue Packages file
- new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description,
- (*Target)->ShortDesc, ExpectedIndexMD5);
+ // Queue Packages file (either diff or full packages files, depending
+ // on the users option)
+ if(_config->FindB("Acquire::PDiffs",true) == true)
+ new pkgAcqDiffIndex(Owner, (*Target)->URI, (*Target)->Description,
+ (*Target)->ShortDesc, ExpectedIndexMD5);
+ else
+ new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description,
+ (*Target)->ShortDesc, ExpectedIndexMD5);
}
}
diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h
index da1bea801..3649d7a03 100644
--- a/apt-pkg/acquire-item.h
+++ b/apt-pkg/acquire-item.h
@@ -82,6 +82,70 @@ class pkgAcquire::Item
virtual ~Item();
};
+// item for index diffs
+
+struct DiffInfo {
+ string file;
+ string sha1;
+ unsigned long size;
+};
+
+class pkgAcqDiffIndex : public pkgAcquire::Item
+{
+ protected:
+ bool Debug;
+ pkgAcquire::ItemDesc Desc;
+ string RealURI;
+ string ExpectedMD5;
+ string CurrentPackagesFile;
+ string Description;
+
+ public:
+ // Specialized action members
+ virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
+ virtual void Done(string Message,unsigned long Size,string Md5Hash,
+ pkgAcquire::MethodConfig *Cnf);
+ virtual string DescURI() {return RealURI + "Index";};
+ virtual string Custom600Headers();
+
+ // helpers
+ bool ParseDiffIndex(string IndexDiffFile);
+
+ pkgAcqDiffIndex(pkgAcquire *Owner,string URI,string URIDesc,
+ string ShortDesct, string ExpectedMD5);
+};
+
+class pkgAcqIndexDiffs : public pkgAcquire::Item
+{
+ protected:
+ bool Debug;
+ pkgAcquire::ItemDesc Desc;
+ string RealURI;
+ string ExpectedMD5;
+
+ // this is the SHA-1 sum we expect after the patching
+ string Description;
+ vector<DiffInfo> available_patches;
+ enum {StateFetchIndex,StateFetchDiff,StateUnzipDiff,StateApplyDiff} State;
+
+ public:
+
+ // Specialized action members
+ virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
+ virtual void Done(string Message,unsigned long Size,string Md5Hash,
+ pkgAcquire::MethodConfig *Cnf);
+ virtual string DescURI() {return RealURI + "Index";};
+
+ // various helpers
+ bool QueueNextDiff();
+ bool ApplyDiff(string PatchFile);
+ void Finish(bool allDone=false);
+
+ pkgAcqIndexDiffs(pkgAcquire *Owner,string URI,string URIDesc,
+ string ShortDesct, string ExpectedMD5,
+ vector<DiffInfo> diffs=vector<DiffInfo>());
+};
+
// Item class for index files
class pkgAcqIndex : public pkgAcquire::Item
{
diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc
index 57cf60bfe..fff1b2b6a 100644
--- a/apt-pkg/acquire.cc
+++ b/apt-pkg/acquire.cc
@@ -818,7 +818,13 @@ bool pkgAcquireStatus::Pulse(pkgAcquire *Owner)
unsigned long ETA =
(unsigned long)((TotalBytes - CurrentBytes) / CurrentCPS);
- snprintf(msg,sizeof(msg), _("Downloading file %li of %li (%s remaining)"), i, TotalItems, TimeToStr(ETA).c_str());
+ // only show the ETA if it makes sense
+ if (ETA > 0 && ETA < 172800 /* two days */ )
+ snprintf(msg,sizeof(msg), _("Retrieving file %li of %li (%s remaining)"), i, TotalItems, TimeToStr(ETA).c_str());
+ else
+ snprintf(msg,sizeof(msg), _("Retrieving file %li of %li"), i, TotalItems);
+
+
// build the status str
status << "dlstatus:" << i
diff --git a/apt-pkg/deb/debversion.cc b/apt-pkg/deb/debversion.cc
index aeee61929..064d8fa5b 100644
--- a/apt-pkg/deb/debversion.cc
+++ b/apt-pkg/deb/debversion.cc
@@ -59,7 +59,7 @@ int debVersioningSystem::CmpFragment(const char *A,const char *AEnd,
}
/* Iterate over the whole string
- What this does is to spilt the whole string into groups of
+ What this does is to split the whole string into groups of
numeric and non numeric portions. For instance:
a67bhgs89
Has 4 portions 'a', '67', 'bhgs', '89'. A more normal:
@@ -140,6 +140,27 @@ int debVersioningSystem::DoCmpVersion(const char *A,const char *AEnd,
if (rhs == BEnd)
rhs = B;
+ // Special case: a zero epoch is the same as no epoch,
+ // so remove it.
+ if (lhs != A)
+ {
+ for (; *A == '0'; ++A);
+ if (A == lhs)
+ {
+ ++A;
+ ++lhs;
+ }
+ }
+ if (rhs != B)
+ {
+ for (; *B == '0'; ++B);
+ if (B == rhs)
+ {
+ ++B;
+ ++rhs;
+ }
+ }
+
// Compare the epoch
int Res = CmpFragment(A,lhs,B,rhs);
if (Res != 0)
diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc
index fe8fbca74..667db8ff2 100644
--- a/apt-pkg/deb/dpkgpm.cc
+++ b/apt-pkg/deb/dpkgpm.cc
@@ -375,8 +375,8 @@ bool pkgDPkgPM::Go(int OutStatusFd)
},
// Purge operation
{
- {"config-files", _("Preparing for remove with config %s")},
- {"not-installed", _("Removed with config %s")},
+ {"config-files", _("Preparing to completely remove %s")},
+ {"not-installed", _("Completely removed %s")},
{NULL, NULL}
},
};
@@ -623,8 +623,8 @@ bool pkgDPkgPM::Go(int OutStatusFd)
'status: conffile-prompt: conffile : 'current-conffile' 'new-conffile' useredited distedited
*/
- char* list[4];
- TokSplitString(':', line, list, 5);
+ char* list[5];
+ TokSplitString(':', line, list, sizeof(list)/sizeof(list[0]));
char *pkg = list[1];
char *action = _strstrip(list[2]);
diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc
index 1fa007940..fc020436c 100644
--- a/apt-pkg/tagfile.cc
+++ b/apt-pkg/tagfile.cc
@@ -35,20 +35,20 @@ pkgTagFile::pkgTagFile(FileFd *pFd,unsigned long Size) :
Fd(*pFd),
Size(Size)
{
- if (Fd.IsOpen() == false)
+ if (Fd.IsOpen() == false || Fd.Size() == 0)
{
Buffer = 0;
Start = End = Buffer = 0;
- Done = true;
iOffset = 0;
+ Map = NULL;
return;
}
- Buffer = new char[Size];
- Start = End = Buffer;
- Done = false;
+ Map = new MMap (Fd, MMap::Public | MMap::ReadOnly);
+ Buffer = (char *) Map->Data ();
+ Start = Buffer;
+ End = Buffer + Map->Size ();
iOffset = 0;
- Fill();
}
/*}}}*/
// TagFile::~pkgTagFile - Destructor /*{{{*/
@@ -56,7 +56,7 @@ pkgTagFile::pkgTagFile(FileFd *pFd,unsigned long Size) :
/* */
pkgTagFile::~pkgTagFile()
{
- delete [] Buffer;
+ delete Map;
}
/*}}}*/
// TagFile::Step - Advance to the next section /*{{{*/
@@ -64,14 +64,13 @@ pkgTagFile::~pkgTagFile()
/* If the Section Scanner fails we refill the buffer and try again. */
bool pkgTagFile::Step(pkgTagSection &Tag)
{
+ if (Start == End)
+ return false;
+
if (Tag.Scan(Start,End - Start) == false)
{
- 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());
+ return _error->Error(_("Unable to parse package file %s (1)"),
+ Fd.Name().c_str());
}
Start += Tag.size();
iOffset += Tag.size();
@@ -80,50 +79,6 @@ 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
@@ -141,20 +96,7 @@ bool pkgTagFile::Jump(pkgTagSection &Tag,unsigned long Offset)
// Reposition and reload..
iOffset = Offset;
- Done = false;
- if (Fd.Seek(Offset) == false)
- return false;
- End = Start = Buffer;
-
- 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;
+ Start = Buffer + iOffset;
if (Tag.Scan(Start,End - Start) == false)
return _error->Error(_("Unable to parse package file %s (2)"),Fd.Name().c_str());
@@ -181,7 +123,7 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength)
Stop = Section = Start;
memset(AlphaIndexes,0,sizeof(AlphaIndexes));
- if (Stop == 0)
+ if (Stop == 0 || MaxLength == 0)
return false;
TagCount = 0;
@@ -212,6 +154,12 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength)
Stop++;
}
+ if ((Stop+1 >= End) && (End[-1] == '\n' || End[-1] == '\r'))
+ {
+ Indexes[TagCount] = (End - 1) - Section;
+ return true;
+ }
+
return false;
}
/*}}}*/
diff --git a/apt-pkg/tagfile.h b/apt-pkg/tagfile.h
index 8c948754d..5cff2681c 100644
--- a/apt-pkg/tagfile.h
+++ b/apt-pkg/tagfile.h
@@ -25,6 +25,7 @@
#endif
#include <apt-pkg/fileutl.h>
+#include <apt-pkg/mmap.h>
#include <stdio.h>
class pkgTagSection
@@ -69,15 +70,13 @@ class pkgTagSection
class pkgTagFile
{
FileFd &Fd;
+ MMap *Map;
char *Buffer;
char *Start;
char *End;
- bool Done;
unsigned long iOffset;
unsigned long Size;
- bool Fill();
-
public:
bool Step(pkgTagSection &Section);