summaryrefslogtreecommitdiff
path: root/apt-pkg
diff options
context:
space:
mode:
Diffstat (limited to 'apt-pkg')
-rw-r--r--apt-pkg/acquire-item.cc627
-rw-r--r--apt-pkg/acquire-item.h763
-rw-r--r--apt-pkg/acquire-method.cc12
-rw-r--r--apt-pkg/acquire-method.h13
-rw-r--r--apt-pkg/acquire-worker.cc29
-rw-r--r--apt-pkg/acquire-worker.h262
-rw-r--r--apt-pkg/acquire.cc24
-rw-r--r--apt-pkg/acquire.h550
-rw-r--r--apt-pkg/algorithms.cc142
-rw-r--r--apt-pkg/algorithms.h3
-rw-r--r--apt-pkg/cachefile.cc51
-rw-r--r--apt-pkg/cachefile.h3
-rw-r--r--apt-pkg/cacheiterators.h87
-rw-r--r--apt-pkg/cdrom.cc78
-rw-r--r--apt-pkg/cdrom.h10
-rw-r--r--apt-pkg/clean.cc4
-rw-r--r--apt-pkg/clean.h3
-rw-r--r--apt-pkg/contrib/cdromutl.cc3
-rw-r--r--apt-pkg/contrib/cdromutl.h7
-rw-r--r--apt-pkg/contrib/cmndline.cc3
-rw-r--r--apt-pkg/contrib/cmndline.h4
-rw-r--r--apt-pkg/contrib/configuration.cc15
-rw-r--r--apt-pkg/contrib/configuration.h4
-rw-r--r--apt-pkg/contrib/crc-16.cc4
-rw-r--r--apt-pkg/contrib/crc-16.h4
-rw-r--r--apt-pkg/contrib/error.cc8
-rw-r--r--apt-pkg/contrib/error.h4
-rw-r--r--apt-pkg/contrib/fileutl.cc6
-rw-r--r--apt-pkg/contrib/fileutl.h3
-rw-r--r--apt-pkg/contrib/hashes.cc89
-rw-r--r--apt-pkg/contrib/hashes.h38
-rw-r--r--apt-pkg/contrib/md5.cc5
-rw-r--r--apt-pkg/contrib/md5.h4
-rw-r--r--apt-pkg/contrib/mmap.cc10
-rw-r--r--apt-pkg/contrib/mmap.h3
-rw-r--r--apt-pkg/contrib/progress.cc7
-rw-r--r--apt-pkg/contrib/progress.h3
-rw-r--r--apt-pkg/contrib/sha1.cc4
-rw-r--r--apt-pkg/contrib/sha1.h5
-rw-r--r--apt-pkg/contrib/sha256.cc430
-rw-r--r--apt-pkg/contrib/sha256.h71
-rw-r--r--apt-pkg/contrib/strutl.cc54
-rw-r--r--apt-pkg/contrib/strutl.h8
-rw-r--r--apt-pkg/deb/debindexfile.cc180
-rw-r--r--apt-pkg/deb/debindexfile.h34
-rw-r--r--apt-pkg/deb/deblistparser.cc48
-rw-r--r--apt-pkg/deb/deblistparser.h4
-rw-r--r--apt-pkg/deb/debmetaindex.cc25
-rw-r--r--apt-pkg/deb/debmetaindex.h4
-rw-r--r--apt-pkg/deb/debrecords.cc72
-rw-r--r--apt-pkg/deb/debrecords.h9
-rw-r--r--apt-pkg/deb/debsrcrecords.cc34
-rw-r--r--apt-pkg/deb/debsrcrecords.h13
-rw-r--r--apt-pkg/deb/debsystem.cc4
-rw-r--r--apt-pkg/deb/debsystem.h4
-rw-r--r--apt-pkg/deb/debversion.cc3
-rw-r--r--apt-pkg/deb/debversion.h4
-rw-r--r--apt-pkg/deb/dpkgpm.cc531
-rw-r--r--apt-pkg/deb/dpkgpm.h43
-rw-r--r--apt-pkg/depcache.cc611
-rw-r--r--apt-pkg/depcache.h228
-rw-r--r--apt-pkg/indexcopy.cc196
-rw-r--r--apt-pkg/indexcopy.h13
-rw-r--r--apt-pkg/indexfile.cc68
-rw-r--r--apt-pkg/indexfile.h10
-rw-r--r--apt-pkg/indexrecords.cc51
-rw-r--r--apt-pkg/indexrecords.h7
-rw-r--r--apt-pkg/init.cc22
-rw-r--r--apt-pkg/init.h6
-rw-r--r--apt-pkg/makefile8
-rw-r--r--apt-pkg/metaindex.h3
-rw-r--r--apt-pkg/orderlist.cc20
-rw-r--r--apt-pkg/orderlist.h3
-rw-r--r--apt-pkg/packagemanager.cc97
-rw-r--r--apt-pkg/packagemanager.h25
-rw-r--r--apt-pkg/pkgcache.cc50
-rw-r--r--apt-pkg/pkgcache.h56
-rw-r--r--apt-pkg/pkgcachegen.cc129
-rw-r--r--apt-pkg/pkgcachegen.h11
-rw-r--r--apt-pkg/pkgrecords.cc39
-rw-r--r--apt-pkg/pkgrecords.h13
-rw-r--r--apt-pkg/pkgsystem.cc5
-rw-r--r--apt-pkg/pkgsystem.h3
-rw-r--r--apt-pkg/policy.cc12
-rw-r--r--apt-pkg/policy.h3
-rw-r--r--apt-pkg/sourcelist.cc4
-rw-r--r--apt-pkg/sourcelist.h3
-rw-r--r--apt-pkg/srcrecords.cc4
-rw-r--r--apt-pkg/srcrecords.h3
-rw-r--r--apt-pkg/tagfile.cc141
-rw-r--r--apt-pkg/tagfile.h15
-rw-r--r--apt-pkg/vendor.cc4
-rw-r--r--apt-pkg/vendor.h3
-rw-r--r--apt-pkg/vendorlist.cc2
-rw-r--r--apt-pkg/vendorlist.h3
-rw-r--r--apt-pkg/version.cc4
-rw-r--r--apt-pkg/version.h3
-rw-r--r--apt-pkg/versionmatch.cc3
-rw-r--r--apt-pkg/versionmatch.h3
99 files changed, 5423 insertions, 930 deletions
diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc
index 1fa929aad..7cae6c8b7 100644
--- a/apt-pkg/acquire-item.cc
+++ b/apt-pkg/acquire-item.cc
@@ -13,9 +13,6 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/acquire-item.h"
-#endif
#include <apt-pkg/acquire-item.h>
#include <apt-pkg/configuration.h>
#include <apt-pkg/sourcelist.h>
@@ -24,6 +21,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 +30,7 @@
#include <unistd.h>
#include <errno.h>
#include <string>
+#include <sstream>
#include <stdio.h>
/*}}}*/
@@ -95,12 +95,13 @@ void pkgAcquire::Item::Start(string /*Message*/,unsigned long Size)
// Acquire::Item::Done - Item downloaded OK /*{{{*/
// ---------------------------------------------------------------------
/* */
-void pkgAcquire::Item::Done(string Message,unsigned long Size,string,
+void pkgAcquire::Item::Done(string Message,unsigned long Size,string Hash,
pkgAcquire::MethodConfig *Cnf)
{
// 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 +132,427 @@ 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,
+ HashString ExpectedHash)
+ : Item(Owner), RealURI(URI), ExpectedHash(ExpectedHash),
+ 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);
+ }
+ }
+ }
+
+ // we have something, queue the next diff
+ if(found)
+ {
+ // queue the diffs
+ string::size_type last_space = Description.rfind(" ");
+ if(last_space != string::npos)
+ Description.erase(last_space, Description.size()-last_space);
+ new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc,
+ ExpectedHash, available_patches);
+ Complete = false;
+ Status = StatDone;
+ Dequeue();
+ return true;
+ }
+ }
+
+ // Nothing found, report and return false
+ // Failing here is ok, if we return false later, the full
+ // IndexFile is queued
+ if(Debug)
+ std::clog << "Can't find a patch in the index file" << std::endl;
+ 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,
+ ExpectedHash);
+
+ 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,
+ HashString ExpectedHash,
+ vector<DiffInfo> diffs)
+ : Item(Owner), RealURI(URI), ExpectedHash(ExpectedHash),
+ available_patches(diffs)
+{
+
+ DestFile = _config->FindDir("Dir::State::lists") + "partial/";
+ DestFile += URItoFileName(URI);
+
+ Debug = _config->FindB("Debug::pkgAcquire::Diffs",false);
+
+ 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,
+ ExpectedHash);
+ 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);
+
+ if(!ExpectedHash.empty() && !ExpectedHash.VerifyFile(DestFile))
+ {
+ 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 = 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);
+ chmod(FinalFile.c_str(),0644);
+
+ // see if there is more to download
+ if(available_patches.size() > 0) {
+ new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc,
+ ExpectedHash, 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)
+ HashString ExpectedHash, string comprExt)
+ : Item(Owner), RealURI(URI), ExpectedHash(ExpectedHash)
{
Decompression = false;
Erase = false;
@@ -149,7 +563,7 @@ pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner,
if(comprExt.empty())
{
// autoselect the compression method
- if(FileExists("/usr/bin/bzip2"))
+ if(FileExists("/bin/bzip2"))
CompressionExtension = ".bz2";
else
CompressionExtension = ".gz";
@@ -189,14 +603,20 @@ void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
// retry with a gzip one
new pkgAcqIndex(Owner, RealURI, Desc.Description,Desc.ShortDesc,
- ExpectedMD5, string(".gz"));
+ ExpectedHash, string(".gz"));
Status = StatDone;
Complete = false;
Dequeue();
return;
+ }
+
+ // on decompression failure, remove bad versions in partial/
+ if(Decompression && Erase) {
+ string s = _config->FindDir("Dir::State::lists") + "partial/";
+ s += URItoFileName(RealURI);
+ unlink(s.c_str());
}
-
Item::Failed(Message,Cnf);
}
@@ -208,32 +628,23 @@ void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
to the uncompressed version of the file. If this is so the file
is copied into the partial directory. In all other cases the file
is decompressed with a gzip uri. */
-void pkgAcqIndex::Done(string Message,unsigned long Size,string MD5,
+void pkgAcqIndex::Done(string Message,unsigned long Size,string Hash,
pkgAcquire::MethodConfig *Cfg)
{
- Item::Done(Message,Size,MD5,Cfg);
+ Item::Done(Message,Size,Hash,Cfg);
if (Decompression == true)
{
if (_config->FindB("Debug::pkgAcquire::Auth", false))
{
- std::cerr << std::endl << RealURI << ": Computed MD5: " << MD5;
- std::cerr << " Expected MD5: " << ExpectedMD5 << std::endl;
- }
-
- if (MD5.empty())
- {
- MD5Summation sum;
- FileFd Fd(DestFile, FileFd::ReadOnly);
- sum.AddFD(Fd.Fd(), Fd.Size());
- Fd.Close();
- MD5 = (string)sum.Result();
+ std::cerr << std::endl << RealURI << ": Computed Hash: " << Hash;
+ std::cerr << " Expected Hash: " << ExpectedHash.toStr() << std::endl;
}
- if (!ExpectedMD5.empty() && MD5 != ExpectedMD5)
+ if (!ExpectedHash.empty() && ExpectedHash.toStr() != Hash)
{
Status = StatAuthError;
- ErrorText = _("MD5Sum mismatch");
+ ErrorText = _("Hash Sum mismatch");
Rename(DestFile,DestFile + ".FAILED");
return;
}
@@ -264,7 +675,6 @@ void pkgAcqIndex::Done(string Message,unsigned long Size,string MD5,
// The files timestamp matches
if (StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false) == true)
return;
-
Decompression = true;
Local = true;
DestFile += ".decomp";
@@ -291,7 +701,7 @@ void pkgAcqIndex::Done(string Message,unsigned long Size,string MD5,
Local = true;
string compExt = Desc.URI.substr(Desc.URI.size()-3);
- char *decompProg;
+ const char *decompProg;
if(compExt == "bz2")
decompProg = "bzip2";
else if(compExt == ".gz")
@@ -308,6 +718,35 @@ void pkgAcqIndex::Done(string Message,unsigned long Size,string MD5,
Mode = decompProg;
}
+// AcqIndexTrans::pkgAcqIndexTrans - Constructor /*{{{*/
+// ---------------------------------------------------------------------
+/* The Translation file is added to the queue */
+pkgAcqIndexTrans::pkgAcqIndexTrans(pkgAcquire *Owner,
+ string URI,string URIDesc,string ShortDesc)
+ : pkgAcqIndex(Owner, URI, URIDesc, ShortDesc, HashString(), "")
+{
+}
+
+ /*}}}*/
+// AcqIndexTrans::Failed - Silence failure messages for missing files /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void pkgAcqIndexTrans::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
+{
+ if (Cnf->LocalOnly == true ||
+ StringToBool(LookupTag(Message,"Transient-Failure"),false) == false)
+ {
+ // Ignore this
+ Status = StatDone;
+ Complete = false;
+ Dequeue();
+ return;
+ }
+
+ Item::Failed(Message,Cnf);
+}
+ /*}}}*/
+
pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner,
string URI,string URIDesc,string ShortDesc,
string MetaIndexURI, string MetaIndexURIDesc,
@@ -321,8 +760,9 @@ pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner,
DestFile = _config->FindDir("Dir::State::lists") + "partial/";
DestFile += URItoFileName(URI);
- // remove any partial downloaded sig-file. it may confuse proxies
- // and is too small to warrant a partial download anyway
+ // remove any partial downloaded sig-file in partial/.
+ // it may confuse proxies and is too small to warrant a
+ // partial download anyway
unlink(DestFile.c_str());
// Create the item
@@ -330,16 +770,19 @@ pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner,
Desc.Owner = this;
Desc.ShortDesc = ShortDesc;
Desc.URI = URI;
-
string Final = _config->FindDir("Dir::State::lists");
Final += URItoFileName(RealURI);
struct stat Buf;
if (stat(Final.c_str(),&Buf) == 0)
{
- // File was already in place. It needs to be re-verified
- // because Release might have changed, so Move it into partial
- Rename(Final,DestFile);
+ // File was already in place. It needs to be re-downloaded/verified
+ // because Release might have changed, we do give it a differnt
+ // name than DestFile because otherwise the http method will
+ // send If-Range requests and there are too many broken servers
+ // out there that do not understand them
+ LastGoodSig = DestFile+".reverify";
+ Rename(Final,LastGoodSig);
}
QueueURI(Desc);
@@ -351,7 +794,7 @@ pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner,
string pkgAcqMetaSig::Custom600Headers()
{
struct stat Buf;
- if (stat(DestFile.c_str(),&Buf) != 0)
+ if (stat(LastGoodSig.c_str(),&Buf) != 0)
return "\nIndex-File: true";
return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
@@ -381,6 +824,12 @@ void pkgAcqMetaSig::Done(string Message,unsigned long Size,string MD5,
Complete = true;
+ // put the last known good file back on i-m-s hit (it will
+ // be re-verified again)
+ // Else do nothing, we have the new file in DestFile then
+ if(StringToBool(LookupTag(Message,"IMS-Hit"),false) == true)
+ Rename(LastGoodSig, DestFile);
+
// queue a pkgAcqMetaIndex to be verified against the sig we just retrieved
new pkgAcqMetaIndex(Owner, MetaIndexURI, MetaIndexURIDesc, MetaIndexShortDesc,
DestFile, IndexTargets, MetaIndexParser);
@@ -389,17 +838,22 @@ void pkgAcqMetaSig::Done(string Message,unsigned long Size,string MD5,
/*}}}*/
void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
{
+ string Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI);
// if we get a network error we fail gracefully
- if(LookupTag(Message,"FailReason") == "Timeout" ||
- LookupTag(Message,"FailReason") == "TmpResolveFailure" ||
- LookupTag(Message,"FailReason") == "ConnectionRefused") {
+ if(Status == StatTransientNetworkError)
+ {
Item::Failed(Message,Cnf);
+ // move the sigfile back on transient network failures
+ if(FileExists(DestFile))
+ Rename(LastGoodSig,Final);
+
+ // set the status back to , Item::Failed likes to reset it
+ Status = pkgAcquire::Item::StatTransientNetworkError;
return;
}
// Delete any existing sigfile when the acquire failed
- string Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI);
unlink(Final.c_str());
// queue a pkgAcqMetaIndex with no sigfile
@@ -424,8 +878,8 @@ pkgAcqMetaIndex::pkgAcqMetaIndex(pkgAcquire *Owner,
string SigFile,
const vector<struct IndexTarget*>* IndexTargets,
indexRecords* MetaIndexParser) :
- Item(Owner), RealURI(URI), SigFile(SigFile), AuthPass(false),
- MetaIndexParser(MetaIndexParser), IndexTargets(IndexTargets), IMSHit(false)
+ Item(Owner), RealURI(URI), SigFile(SigFile), IndexTargets(IndexTargets),
+ MetaIndexParser(MetaIndexParser), AuthPass(false), IMSHit(false)
{
DestFile = _config->FindDir("Dir::State::lists") + "partial/";
DestFile += URItoFileName(URI);
@@ -455,10 +909,10 @@ string pkgAcqMetaIndex::Custom600Headers()
return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
}
-void pkgAcqMetaIndex::Done(string Message,unsigned long Size,string MD5,
+void pkgAcqMetaIndex::Done(string Message,unsigned long Size,string Hash,
pkgAcquire::MethodConfig *Cfg)
{
- Item::Done(Message,Size,MD5,Cfg);
+ Item::Done(Message,Size,Hash,Cfg);
// MetaIndexes are done in two passes: one to download the
// metaindex with an appropriate method, and a second to verify it
@@ -520,18 +974,19 @@ void pkgAcqMetaIndex::RetrievalDone(string Message)
// see if the download was a IMSHit
IMSHit = StringToBool(LookupTag(Message,"IMS-Hit"),false);
-
Complete = true;
string FinalFile = _config->FindDir("Dir::State::lists");
FinalFile += URItoFileName(RealURI);
- // The files timestamp matches
- if (StringToBool(LookupTag(Message,"IMS-Hit"),false) == false)
- {
- // Move it into position
+ // If we get a IMS hit we can remove the empty file in partial
+ // othersie we move the file in place
+ if (IMSHit)
+ unlink(DestFile.c_str());
+ else
Rename(DestFile,FinalFile);
- }
+
+ chmod(FinalFile.c_str(),0644);
DestFile = FinalFile;
}
@@ -575,7 +1030,7 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify)
Target != IndexTargets->end();
Target++)
{
- string ExpectedIndexMD5;
+ HashString ExpectedIndexHash;
if (verify)
{
const indexRecords::checkSum *Record = MetaIndexParser->Lookup((*Target)->MetaKey);
@@ -586,24 +1041,29 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify)
+ (*Target)->MetaKey + " in Meta-index file (malformed Release file?)";
return;
}
- ExpectedIndexMD5 = Record->MD5Hash;
+ ExpectedIndexHash = Record->Hash;
if (_config->FindB("Debug::pkgAcquire::Auth", false))
{
std::cerr << "Queueing: " << (*Target)->URI << std::endl;
- std::cerr << "Expected MD5: " << ExpectedIndexMD5 << std::endl;
+ std::cerr << "Expected Hash: " << ExpectedIndexHash.toStr() << std::endl;
}
- if (ExpectedIndexMD5.empty())
+ if (ExpectedIndexHash.empty())
{
Status = StatAuthError;
- ErrorText = "Unable to find MD5 sum for "
+ ErrorText = "Unable to find hash sum for "
+ (*Target)->MetaKey + " in Meta-index file";
return;
}
}
- // 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, ExpectedIndexHash);
+ else
+ new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description,
+ (*Target)->ShortDesc, ExpectedIndexHash);
}
}
@@ -637,7 +1097,7 @@ bool pkgAcqMetaIndex::VerifyVendor(string Message)
// check for missing sigs (that where not fatal because otherwise we had
// bombed earlier)
string missingkeys;
- string msg = _("There are no public key available for the "
+ string msg = _("There is no public key available for the "
"following key IDs:\n");
pos = Message.find("NO_PUBKEY ");
if (pos != std::string::npos)
@@ -843,7 +1303,12 @@ bool pkgAcqArchive::QueueNext()
return false;
string PkgFile = Parse.FileName();
- MD5 = Parse.MD5Hash();
+ if(Parse.SHA256Hash() != "")
+ ExpectedHash = HashString("SHA256", Parse.SHA256Hash());
+ else if (Parse.SHA1Hash() != "")
+ ExpectedHash = HashString("SHA1", Parse.SHA1Hash());
+ else
+ ExpectedHash = HashString("MD5Sum", Parse.MD5Hash());
if (PkgFile.empty() == true)
return _error->Error(_("The package index files are corrupted. No Filename: "
"field for package %s."),
@@ -923,10 +1388,10 @@ bool pkgAcqArchive::QueueNext()
// AcqArchive::Done - Finished fetching /*{{{*/
// ---------------------------------------------------------------------
/* */
-void pkgAcqArchive::Done(string Message,unsigned long Size,string Md5Hash,
+void pkgAcqArchive::Done(string Message,unsigned long Size,string CalcHash,
pkgAcquire::MethodConfig *Cfg)
{
- Item::Done(Message,Size,Md5Hash,Cfg);
+ Item::Done(Message,Size,CalcHash,Cfg);
// Check the size
if (Size != Version->Size)
@@ -936,17 +1401,14 @@ void pkgAcqArchive::Done(string Message,unsigned long Size,string Md5Hash,
return;
}
- // Check the md5
- if (Md5Hash.empty() == false && MD5.empty() == false)
+ // Check the hash
+ if(ExpectedHash.toStr() != CalcHash)
{
- if (Md5Hash != MD5)
- {
- Status = StatError;
- ErrorText = _("MD5Sum mismatch");
- if(FileExists(DestFile))
- Rename(DestFile,DestFile + ".FAILED");
- return;
- }
+ Status = StatError;
+ ErrorText = _("Hash Sum mismatch");
+ if(FileExists(DestFile))
+ Rename(DestFile,DestFile + ".FAILED");
+ return;
}
// Grab the output filename
@@ -1038,10 +1500,10 @@ void pkgAcqArchive::Finished()
// AcqFile::pkgAcqFile - Constructor /*{{{*/
// ---------------------------------------------------------------------
/* The file is added to the queue */
-pkgAcqFile::pkgAcqFile(pkgAcquire *Owner,string URI,string MD5,
+pkgAcqFile::pkgAcqFile(pkgAcquire *Owner,string URI,string Hash,
unsigned long Size,string Dsc,string ShortDesc,
const string &DestDir, const string &DestFilename) :
- Item(Owner), Md5Hash(MD5)
+ Item(Owner), ExpectedHash(Hash)
{
Retries = _config->FindI("Acquire::Retries",0);
@@ -1078,23 +1540,20 @@ pkgAcqFile::pkgAcqFile(pkgAcquire *Owner,string URI,string MD5,
// AcqFile::Done - Item downloaded OK /*{{{*/
// ---------------------------------------------------------------------
/* */
-void pkgAcqFile::Done(string Message,unsigned long Size,string MD5,
+void pkgAcqFile::Done(string Message,unsigned long Size,string CalcHash,
pkgAcquire::MethodConfig *Cnf)
{
- // Check the md5
- if (Md5Hash.empty() == false && MD5.empty() == false)
+ Item::Done(Message,Size,CalcHash,Cnf);
+
+ // Check the hash
+ if(!ExpectedHash.empty() && ExpectedHash.toStr() != CalcHash)
{
- if (Md5Hash != MD5)
- {
- Status = StatError;
- ErrorText = "MD5Sum mismatch";
- Rename(DestFile,DestFile + ".FAILED");
- return;
- }
+ Status = StatError;
+ ErrorText = "Hash Sum mismatch";
+ Rename(DestFile,DestFile + ".FAILED");
+ return;
}
- Item::Done(Message,Size,MD5,Cnf);
-
string FileName = LookupTag(Message,"Filename");
if (FileName.empty() == true)
{
diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h
index da1bea801..a48f7f7e5 100644
--- a/apt-pkg/acquire-item.h
+++ b/apt-pkg/acquire-item.h
@@ -9,10 +9,10 @@
the Owner Acquire class. Derived classes will then call QueueURI to
register all the URI's they wish to fetch at the initial moment.
- Two item classes are provided to provide functionality for downloading
- of Index files and downloading of Packages.
+ Three item classes are provided to provide functionality for
+ downloading of Index, Translation and Packages files.
- A Archive class is provided for downloading .deb files. It does Md5
+ A Archive class is provided for downloading .deb files. It does Hash
checking and source location as well as a retry algorithm.
##################################################################### */
@@ -26,72 +26,493 @@
#include <apt-pkg/sourcelist.h>
#include <apt-pkg/pkgrecords.h>
#include <apt-pkg/indexrecords.h>
+#include <apt-pkg/hashes.h>
-#ifdef __GNUG__
-#pragma interface "apt-pkg/acquire-item.h"
-#endif
+/** \addtogroup acquire
+ * @{
+ *
+ * \file acquire-item.h
+ */
-// Item to acquire
+/** \brief Represents the process by which a pkgAcquire object should
+ * retrieve a file or a collection of files.
+ *
+ * By convention, Item subclasses should insert themselves into the
+ * acquire queue when they are created by calling QueueURI(), and
+ * remove themselves by calling Dequeue() when either Done() or
+ * Failed() is invoked. Item objects are also responsible for
+ * notifying the download progress indicator (accessible via
+ * #Owner->Log) of their status.
+ *
+ * \see pkgAcquire
+ */
class pkgAcquire::Item
{
protected:
- // Some private helper methods for registering URIs
+ /** \brief The acquire object with which this item is associated. */
pkgAcquire *Owner;
+
+ /** \brief Insert this item into its owner's queue.
+ *
+ * \param ItemDesc Metadata about this item (its URI and
+ * description).
+ */
inline void QueueURI(ItemDesc &Item)
{Owner->Enqueue(Item);};
+
+ /** \brief Remove this item from its owner's queue. */
inline void Dequeue() {Owner->Dequeue(this);};
- // Safe rename function with timestamp preservation
+ /** \brief Rename a file without modifying its timestamp.
+ *
+ * Many item methods call this as their final action.
+ *
+ * \param From The file to be renamed.
+ *
+ * \param To The new name of #From. If #To exists it will be
+ * overwritten.
+ */
void Rename(string From,string To);
public:
- // State of the item
- enum {StatIdle, StatFetching, StatDone, StatError, StatAuthError} Status;
+ /** \brief The current status of this item. */
+ enum ItemState
+ {
+ /** \brief The item is waiting to be downloaded. */
+ StatIdle,
+
+ /** \brief The item is currently being downloaded. */
+ StatFetching,
+
+ /** \brief The item has been successfully downloaded. */
+ StatDone,
+
+ /** \brief An error was encountered while downloading this
+ * item.
+ */
+ StatError,
+
+ /** \brief The item was downloaded but its authenticity could
+ * not be verified.
+ */
+ StatAuthError,
+
+ /** \brief The item was could not be downloaded because of
+ * a transient network error (e.g. network down)
+ */
+ StatTransientNetworkError
+ } Status;
+
+ /** \brief Contains a textual description of the error encountered
+ * if #Status is #StatError or #StatAuthError.
+ */
string ErrorText;
+
+ /** \brief The size of the object to fetch. */
unsigned long FileSize;
- unsigned long PartialSize;
+
+ /** \brief How much of the object was already fetched. */
+ unsigned long PartialSize;
+
+ /** \brief If not \b NULL, contains the name of a subprocess that
+ * is operating on this object (for instance, "gzip" or "gpgv").
+ */
const char *Mode;
+
+ /** \brief A client-supplied unique identifier.
+ *
+ * This field is initalized to 0; it is meant to be filled in by
+ * clients that wish to use it to uniquely identify items.
+ *
+ * \todo it's unused in apt itself
+ */
unsigned long ID;
+
+ /** \brief If \b true, the entire object has been successfully fetched.
+ *
+ * Subclasses should set this to \b true when appropriate.
+ */
bool Complete;
+
+ /** \brief If \b true, the URI of this object is "local".
+ *
+ * The only effect of this field is to exclude the object from the
+ * download progress indicator's overall statistics.
+ */
bool Local;
- // Number of queues we are inserted into
+ /** \brief The number of fetch queues into which this item has been
+ * inserted.
+ *
+ * There is one queue for each source from which an item could be
+ * downloaded.
+ *
+ * \sa pkgAcquire
+ */
unsigned int QueueCounter;
- // File to write the fetch into
+ /** \brief The name of the file into which the retrieved object
+ * will be written.
+ */
string DestFile;
- // Action members invoked by the worker
+ /** \brief Invoked by the acquire worker when the object couldn't
+ * be fetched.
+ *
+ * This is a branch of the continuation of the fetch process.
+ *
+ * \param Message An RFC822-formatted message from the acquire
+ * method describing what went wrong. Use LookupTag() to parse
+ * it.
+ *
+ * \param Cnf The method via which the worker tried to fetch this object.
+ *
+ * \sa pkgAcqMethod
+ */
virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
- virtual void Done(string Message,unsigned long Size,string Md5Hash,
+
+ /** \brief Invoked by the acquire worker when the object was
+ * fetched successfully.
+ *
+ * Note that the object might \e not have been written to
+ * DestFile; check for the presence of an Alt-Filename entry in
+ * Message to find the file to which it was really written.
+ *
+ * Done is often used to switch from one stage of the processing
+ * to the next (e.g. fetching, unpacking, copying). It is one
+ * branch of the continuation of the fetch process.
+ *
+ * \param Message Data from the acquire method. Use LookupTag()
+ * to parse it.
+ * \param Size The size of the object that was fetched.
+ * \param Hash The HashSum of the object that was fetched.
+ * \param Cnf The method via which the object was fetched.
+ *
+ * \sa pkgAcqMethod
+ */
+ virtual void Done(string Message,unsigned long Size,string Hash,
pkgAcquire::MethodConfig *Cnf);
+
+ /** \brief Invoked when the worker starts to fetch this object.
+ *
+ * \param Message RFC822-formatted data from the worker process.
+ * Use LookupTag() to parse it.
+ *
+ * \param Size The size of the object being fetched.
+ *
+ * \sa pkgAcqMethod
+ */
virtual void Start(string Message,unsigned long Size);
+
+ /** \brief Custom headers to be sent to the fetch process.
+ *
+ * \return a string containing RFC822-style headers that are to be
+ * inserted into the 600 URI Acquire message sent to the fetch
+ * subprocess. The headers are inserted after a newline-less
+ * line, so they should (if nonempty) have a leading newline and
+ * no trailing newline.
+ */
virtual string Custom600Headers() {return string();};
+
+ /** \brief A "descriptive" URI-like string.
+ *
+ * \return a URI that should be used to describe what is being fetched.
+ */
virtual string DescURI() = 0;
+ /** \brief Short item description.
+ *
+ * \return a brief description of the object being fetched.
+ */
virtual string ShortDesc() {return DescURI();}
+
+ /** \brief Invoked by the worker when the download is completely done. */
virtual void Finished() {};
- // Inquire functions
- virtual string MD5Sum() {return string();};
+ /** \brief HashSum
+ *
+ * \return the HashSum of this object, if applicable; otherwise, an
+ * empty string.
+ */
+ virtual string HashSum() {return string();};
+
+ /** \return the acquire process with which this item is associated. */
pkgAcquire *GetOwner() {return Owner;};
+
+ /** \return \b true if this object is being fetched from a trusted source. */
virtual bool IsTrusted() {return false;};
-
+
+ /** \brief Initialize an item.
+ *
+ * Adds the item to the list of items known to the acquire
+ * process, but does not place it into any fetch queues (you must
+ * manually invoke QueueURI() to do so).
+ *
+ * Initializes all fields of the item other than Owner to 0,
+ * false, or the empty string.
+ *
+ * \param Owner The new owner of this item.
+ */
Item(pkgAcquire *Owner);
+
+ /** \brief Remove this item from its owner's queue by invoking
+ * pkgAcquire::Remove.
+ */
virtual ~Item();
};
-// Item class for index files
-class pkgAcqIndex : public pkgAcquire::Item
+/** \brief Information about an index patch (aka diff). */
+struct DiffInfo {
+ /** The filename of the diff. */
+ string file;
+
+ /** The sha1 hash of the diff. */
+ string sha1;
+
+ /** The size of the diff. */
+ unsigned long size;
+};
+
+/** \brief An item that is responsible for fetching an index file of
+ * package list diffs and starting the package list's download.
+ *
+ * This item downloads the Index file and parses it, then enqueues
+ * additional downloads of either the individual patches (using
+ * pkgAcqIndexDiffs) or the entire Packages file (using pkgAcqIndex).
+ *
+ * \sa pkgAcqIndexDiffs, pkgAcqIndex
+ */
+class pkgAcqDiffIndex : public pkgAcquire::Item
+{
+ protected:
+ /** \brief If \b true, debugging information will be written to std::clog. */
+ bool Debug;
+
+ /** \brief The item that is currently being downloaded. */
+ pkgAcquire::ItemDesc Desc;
+
+ /** \brief The URI of the index file to recreate at our end (either
+ * by downloading it or by applying partial patches).
+ */
+ string RealURI;
+
+ /** \brief The Hash that the real index file should have after
+ * all patches have been applied.
+ */
+ HashString ExpectedHash;
+
+ /** \brief The index file which will be patched to generate the new
+ * file.
+ */
+ string CurrentPackagesFile;
+
+ /** \brief A description of the Packages file (stored in
+ * pkgAcquire::ItemDesc::Description).
+ */
+ 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();
+
+ /** \brief Parse the Index file for a set of Packages diffs.
+ *
+ * Parses the Index file and creates additional download items as
+ * necessary.
+ *
+ * \param IndexDiffFile The name of the Index file.
+ *
+ * \return \b true if the Index file was successfully parsed, \b
+ * false otherwise.
+ */
+ bool ParseDiffIndex(string IndexDiffFile);
+
+
+ /** \brief Create a new pkgAcqDiffIndex.
+ *
+ * \param Owner The Acquire object that owns this item.
+ *
+ * \param URI The URI of the list file to download.
+ *
+ * \param URIDesc A long description of the list file to download.
+ *
+ * \param ShortDesc A short description of the list file to download.
+ *
+ * \param ExpectedHash The list file's MD5 signature.
+ */
+ pkgAcqDiffIndex(pkgAcquire *Owner,string URI,string URIDesc,
+ string ShortDesc, HashString ExpectedHash);
+};
+
+/** \brief An item that is responsible for fetching all the patches
+ * that need to be applied to a given package index file.
+ *
+ * After downloading and applying a single patch, this item will
+ * enqueue a new pkgAcqIndexDiffs to download and apply the remaining
+ * patches. If no patch can be found that applies to an intermediate
+ * file or if one of the patches cannot be downloaded, falls back to
+ * downloading the entire package index file using pkgAcqIndex.
+ *
+ * \sa pkgAcqDiffIndex, pkgAcqIndex
+ */
+class pkgAcqIndexDiffs : public pkgAcquire::Item
{
+ private:
+
+ /** \brief Queue up the next diff download.
+ *
+ * Search for the next available diff that applies to the file
+ * that currently exists on disk, and enqueue it by calling
+ * QueueURI().
+ *
+ * \return \b true if an applicable diff was found, \b false
+ * otherwise.
+ */
+ bool QueueNextDiff();
+
+ /** \brief Handle tasks that must be performed after the item
+ * finishes downloading.
+ *
+ * Dequeues the item and checks the resulting file's md5sum
+ * against ExpectedHash after the last patch was applied.
+ * There is no need to check the md5/sha1 after a "normal"
+ * patch because QueueNextDiff() will check the sha1 later.
+ *
+ * \param allDone If \b true, the file was entirely reconstructed,
+ * and its md5sum is verified.
+ */
+ void Finish(bool allDone=false);
+
protected:
+
+ /** \brief If \b true, debugging output will be written to
+ * std::clog.
+ */
+ bool Debug;
+
+ /** \brief A description of the item that is currently being
+ * downloaded.
+ */
+ pkgAcquire::ItemDesc Desc;
+
+ /** \brief The URI of the package index file that is being
+ * reconstructed.
+ */
+ string RealURI;
+
+ /** \brief The HashSum of the package index file that is being
+ * reconstructed.
+ */
+ HashString ExpectedHash;
+
+ /** A description of the file being downloaded. */
+ string Description;
+
+ /** The patches that remain to be downloaded, including the patch
+ * being downloaded right now. This list should be ordered so
+ * that each diff appears before any diff that depends on it.
+ *
+ * \todo These are indexed by sha1sum; why not use some sort of
+ * dictionary instead of relying on ordering and stripping them
+ * off the front?
+ */
+ vector<DiffInfo> available_patches;
+ /** The current status of this patch. */
+ enum DiffState
+ {
+ /** \brief The diff is in an unknown state. */
+ StateFetchUnkown,
+
+ /** \brief The diff is currently being fetched. */
+ StateFetchDiff,
+
+ /** \brief The diff is currently being uncompressed. */
+ StateUnzipDiff,
+
+ /** \brief The diff is currently being applied. */
+ StateApplyDiff
+ } State;
+
+ public:
+ /** \brief Called when the patch file failed to be downloaded.
+ *
+ * This method will fall back to downloading the whole index file
+ * outright; its arguments are ignored.
+ */
+ 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";};
+
+ /** \brief Create an index diff item.
+ *
+ * After filling in its basic fields, this invokes Finish(true) if
+ * #diffs is empty, or QueueNextDiff() otherwise.
+ *
+ * \param Owner The pkgAcquire object that owns this item.
+ *
+ * \param URI The URI of the package index file being
+ * reconstructed.
+ *
+ * \param URIDesc A long description of this item.
+ *
+ * \param ShortDesc A brief description of this item.
+ *
+ * \param ExpectedHash The expected md5sum of the completely
+ * reconstructed package index file; the index file will be tested
+ * against this value when it is entirely reconstructed.
+ *
+ * \param diffs The remaining diffs from the index of diffs. They
+ * should be ordered so that each diff appears before any diff
+ * that depends on it.
+ */
+ pkgAcqIndexDiffs(pkgAcquire *Owner,string URI,string URIDesc,
+ string ShortDesc, HashString ExpectedHash,
+ vector<DiffInfo> diffs=vector<DiffInfo>());
+};
+
+/** \brief An acquire item that is responsible for fetching an index
+ * file (e.g., Packages or Sources).
+ *
+ * \sa pkgAcqDiffIndex, pkgAcqIndexDiffs, pkgAcqIndexTrans
+ *
+ * \todo Why does pkgAcqIndex have protected members?
+ */
+class pkgAcqIndex : public pkgAcquire::Item
+{
+ protected:
+
+ /** \brief If \b true, the index file has been decompressed. */
bool Decompression;
+
+ /** \brief If \b true, the partially downloaded file will be
+ * removed when the download completes.
+ */
bool Erase;
+
+ /** \brief The download request that is currently being
+ * processed.
+ */
pkgAcquire::ItemDesc Desc;
+
+ /** \brief The object that is actually being fetched (minus any
+ * compression-related extensions).
+ */
string RealURI;
- string ExpectedMD5;
+
+ /** \brief The expected hashsum of the decompressed index file. */
+ HashString ExpectedHash;
+
+ /** \brief The compression-related file extension that is being
+ * added to the downloaded file (e.g., ".gz" or ".bz2").
+ */
string CompressionExtension;
public:
@@ -102,27 +523,126 @@ class pkgAcqIndex : public pkgAcquire::Item
pkgAcquire::MethodConfig *Cnf);
virtual string Custom600Headers();
virtual string DescURI() {return RealURI + CompressionExtension;};
+ virtual string HashSum() {return ExpectedHash.toStr(); };
+ /** \brief Create a pkgAcqIndex.
+ *
+ * \param Owner The pkgAcquire object with which this item is
+ * associated.
+ *
+ * \param URI The URI of the index file that is to be downloaded.
+ *
+ * \param URIDesc A "URI-style" description of this index file.
+ *
+ * \param ShortDesc A brief description of this index file.
+ *
+ * \param ExpectedHash The expected hashsum of this index file.
+ *
+ * \param compressExt The compression-related extension with which
+ * this index file should be downloaded, or "" to autodetect
+ * (".bz2" is used if bzip2 is installed, ".gz" otherwise).
+ */
pkgAcqIndex(pkgAcquire *Owner,string URI,string URIDesc,
- string ShortDesct, string ExpectedMD5, string compressExt="");
+ string ShortDesc, HashString ExpectedHash, string compressExt="");
+};
+
+/** \brief An acquire item that is responsible for fetching a
+ * translated index file.
+ *
+ * The only difference from pkgAcqIndex is that transient failures
+ * are suppressed: no error occurs if the translated index file is
+ * missing.
+ */
+class pkgAcqIndexTrans : public pkgAcqIndex
+{
+ public:
+
+ virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
+
+ /** \brief Create a pkgAcqIndexTrans.
+ *
+ * \param Owner The pkgAcquire object with which this item is
+ * associated.
+ *
+ * \param URI The URI of the index file that is to be downloaded.
+ *
+ * \param URIDesc A "URI-style" description of this index file.
+ *
+ * \param ShortDesc A brief description of this index file.
+ *
+ * \param ExpectedHash The expected hashsum of this index file.
+ *
+ * \param compressExt The compression-related extension with which
+ * this index file should be downloaded, or "" to autodetect
+ * (".bz2" is used if bzip2 is installed, ".gz" otherwise).
+ */
+ pkgAcqIndexTrans(pkgAcquire *Owner,string URI,string URIDesc,
+ string ShortDesc);
};
+/** \brief Information about an index file. */
struct IndexTarget
{
+ /** \brief A URI from which the index file can be downloaded. */
string URI;
+
+ /** \brief A description of the index file. */
string Description;
+
+ /** \brief A shorter description of the index file. */
string ShortDesc;
+
+ /** \brief The key by which this index file should be
+ * looked up within the meta signature file.
+ */
string MetaKey;
};
-// Item class for index signatures
+/** \brief An acquire item that downloads the detached signature
+ * of a meta-index (Release) file, then queues up the release
+ * file itself.
+ *
+ * \todo Why protected members?
+ *
+ * \sa pkgAcqMetaIndex
+ */
class pkgAcqMetaSig : public pkgAcquire::Item
{
protected:
-
+ /** \brief The last good signature file */
+ string LastGoodSig;
+
+
+ /** \brief The fetch request that is currently being processed. */
pkgAcquire::ItemDesc Desc;
- string RealURI,MetaIndexURI,MetaIndexURIDesc,MetaIndexShortDesc;
+
+ /** \brief The URI of the signature file. Unlike Desc.URI, this is
+ * never modified; it is used to determine the file that is being
+ * downloaded.
+ */
+ string RealURI;
+
+ /** \brief The URI of the meta-index file to be fetched after the signature. */
+ string MetaIndexURI;
+
+ /** \brief A "URI-style" description of the meta-index file to be
+ * fetched after the signature.
+ */
+ string MetaIndexURIDesc;
+
+ /** \brief A brief description of the meta-index file to be fetched
+ * after the signature.
+ */
+ string MetaIndexShortDesc;
+
+ /** \brief A package-system-specific parser for the meta-index file. */
indexRecords* MetaIndexParser;
+
+ /** \brief The index files which should be looked up in the meta-index
+ * and then downloaded.
+ *
+ * \todo Why a list of pointers instead of a list of structs?
+ */
const vector<struct IndexTarget*>* IndexTargets;
public:
@@ -134,40 +654,102 @@ class pkgAcqMetaSig : public pkgAcquire::Item
virtual string Custom600Headers();
virtual string DescURI() {return RealURI; };
+ /** \brief Create a new pkgAcqMetaSig. */
pkgAcqMetaSig(pkgAcquire *Owner,string URI,string URIDesc, string ShortDesc,
string MetaIndexURI, string MetaIndexURIDesc, string MetaIndexShortDesc,
const vector<struct IndexTarget*>* IndexTargets,
indexRecords* MetaIndexParser);
};
-// Item class for index signatures
+/** \brief An item that is responsible for downloading the meta-index
+ * file (i.e., Release) itself and verifying its signature.
+ *
+ * Once the download and verification are complete, the downloads of
+ * the individual index files are queued up using pkgAcqDiffIndex.
+ * If the meta-index file had a valid signature, the expected hashsums
+ * of the index files will be the md5sums listed in the meta-index;
+ * otherwise, the expected hashsums will be "" (causing the
+ * authentication of the index files to be bypassed).
+ */
class pkgAcqMetaIndex : public pkgAcquire::Item
{
protected:
-
+ /** \brief The fetch command that is currently being processed. */
pkgAcquire::ItemDesc Desc;
- string RealURI; // FIXME: is this redundant w/ Desc.URI?
+
+ /** \brief The URI that is actually being downloaded; never
+ * modified by pkgAcqMetaIndex.
+ */
+ string RealURI;
+
+ /** \brief The file in which the signature for this index was stored.
+ *
+ * If empty, the signature and the md5sums of the individual
+ * indices will not be checked.
+ */
string SigFile;
+
+ /** \brief The index files to download. */
const vector<struct IndexTarget*>* IndexTargets;
+
+ /** \brief The parser for the meta-index file. */
indexRecords* MetaIndexParser;
+
+ /** \brief If \b true, the index's signature is currently being verified.
+ */
bool AuthPass;
// required to deal gracefully with problems caused by incorrect ims hits
bool IMSHit;
+ /** \brief Check that the release file is a release file for the
+ * correct distribution.
+ *
+ * \return \b true if no fatal errors were encountered.
+ */
bool VerifyVendor(string Message);
+
+ /** \brief Called when a file is finished being retrieved.
+ *
+ * If the file was not downloaded to DestFile, a copy process is
+ * set up to copy it to DestFile; otherwise, Complete is set to \b
+ * true and the file is moved to its final location.
+ *
+ * \param Message The message block received from the fetch
+ * subprocess.
+ */
void RetrievalDone(string Message);
+
+ /** \brief Called when authentication succeeded.
+ *
+ * Sanity-checks the authenticated file, queues up the individual
+ * index files for download, and saves the signature in the lists
+ * directory next to the authenticated list file.
+ *
+ * \param Message The message block received from the fetch
+ * subprocess.
+ */
void AuthDone(string Message);
+
+ /** \brief Starts downloading the individual index files.
+ *
+ * \param verify If \b true, only indices whose expected hashsum
+ * can be determined from the meta-index will be downloaded, and
+ * the hashsums of indices will be checked (reporting
+ * #StatAuthError if there is a mismatch). If verify is \b false,
+ * no hashsum checking will be performed.
+ */
void QueueIndexes(bool verify);
public:
// Specialized action members
virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
- virtual void Done(string Message,unsigned long Size,string Md5Hash,
+ virtual void Done(string Message,unsigned long Size, string Hash,
pkgAcquire::MethodConfig *Cnf);
virtual string Custom600Headers();
virtual string DescURI() {return RealURI; };
+ /** \brief Create a new pkgAcqMetaIndex. */
pkgAcqMetaIndex(pkgAcquire *Owner,
string URI,string URIDesc, string ShortDesc,
string SigFile,
@@ -175,65 +757,152 @@ class pkgAcqMetaIndex : public pkgAcquire::Item
indexRecords* MetaIndexParser);
};
-// Item class for archive files
+/** \brief An item that is responsible for fetching a package file.
+ *
+ * If the package file already exists in the cache, nothing will be
+ * done.
+ */
class pkgAcqArchive : public pkgAcquire::Item
{
protected:
-
- // State information for the retry mechanism
+ /** \brief The package version being fetched. */
pkgCache::VerIterator Version;
+
+ /** \brief The fetch command that is currently being processed. */
pkgAcquire::ItemDesc Desc;
+
+ /** \brief The list of sources from which to pick archives to
+ * download this package from.
+ */
pkgSourceList *Sources;
+
+ /** \brief A package records object, used to look up the file
+ * corresponding to each version of the package.
+ */
pkgRecords *Recs;
- string MD5;
+
+ /** \brief The hashsum of this package. */
+ HashString ExpectedHash;
+
+ /** \brief A location in which the actual filename of the package
+ * should be stored.
+ */
string &StoreFilename;
+
+ /** \brief The next file for this version to try to download. */
pkgCache::VerFileIterator Vf;
+
+ /** \brief How many (more) times to try to find a new source from
+ * which to download this package version if it fails.
+ *
+ * Set from Acquire::Retries.
+ */
unsigned int Retries;
+
+ /** \brief \b true if this version file is being downloaded from a
+ * trusted source.
+ */
bool Trusted;
- // Queue the next available file for download.
+ /** \brief Queue up the next available file for this version. */
bool QueueNext();
public:
- // Specialized action members
virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
- virtual void Done(string Message,unsigned long Size,string Md5Hash,
+ virtual void Done(string Message,unsigned long Size,string Hash,
pkgAcquire::MethodConfig *Cnf);
- virtual string MD5Sum() {return MD5;};
virtual string DescURI() {return Desc.URI;};
virtual string ShortDesc() {return Desc.ShortDesc;};
virtual void Finished();
+ virtual string HashSum() {return ExpectedHash.toStr(); };
virtual bool IsTrusted();
+ /** \brief Create a new pkgAcqArchive.
+ *
+ * \param Owner The pkgAcquire object with which this item is
+ * associated.
+ *
+ * \param Sources The sources from which to download version
+ * files.
+ *
+ * \param Recs A package records object, used to look up the file
+ * corresponding to each version of the package.
+ *
+ * \param Version The package version to download.
+ *
+ * \param StoreFilename A location in which the actual filename of
+ * the package should be stored. It will be set to a guessed
+ * basename in the constructor, and filled in with a fully
+ * qualified filename once the download finishes.
+ */
pkgAcqArchive(pkgAcquire *Owner,pkgSourceList *Sources,
pkgRecords *Recs,pkgCache::VerIterator const &Version,
string &StoreFilename);
};
-// Fetch a generic file to the current directory
+/** \brief Retrieve an arbitrary file to the current directory.
+ *
+ * The file is retrieved even if it is accessed via a URL type that
+ * normally is a NOP, such as "file". If the download fails, the
+ * partial file is renamed to get a ".FAILED" extension.
+ */
class pkgAcqFile : public pkgAcquire::Item
{
+ /** \brief The currently active download process. */
pkgAcquire::ItemDesc Desc;
- string Md5Hash;
+
+ /** \brief The hashsum of the file to download, if it is known. */
+ HashString ExpectedHash;
+
+ /** \brief How many times to retry the download, set from
+ * Acquire::Retries.
+ */
unsigned int Retries;
public:
// Specialized action members
virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
- virtual void Done(string Message,unsigned long Size,string Md5Hash,
+ virtual void Done(string Message,unsigned long Size,string CalcHash,
pkgAcquire::MethodConfig *Cnf);
- virtual string MD5Sum() {return Md5Hash;};
virtual string DescURI() {return Desc.URI;};
+ virtual string HashSum() {return ExpectedHash.toStr(); };
- // If DestFilename is empty, download to DestDir/<basename> if
- // DestDir is non-empty, $CWD/<basename> otherwise. If
- // DestFilename is NOT empty, DestDir is ignored and DestFilename
- // is the absolute name to which the file should be downloaded.
- pkgAcqFile(pkgAcquire *Owner, string URI, string MD5, unsigned long Size,
+ /** \brief Create a new pkgAcqFile object.
+ *
+ * \param Owner The pkgAcquire object with which this object is
+ * associated.
+ *
+ * \param URI The URI to download.
+ *
+ * \param Hash The hashsum of the file to download, if it is known;
+ * otherwise "".
+ *
+ * \param Size The size of the file to download, if it is known;
+ * otherwise 0.
+ *
+ * \param Desc A description of the file being downloaded.
+ *
+ * \param ShortDesc A brief description of the file being
+ * downloaded.
+ *
+ * \param DestDir The directory the file should be downloaded into.
+ *
+ * \param DestFilename The filename+path the file is downloaded to.
+ *
+ *
+ * If DestFilename is empty, download to DestDir/<basename> if
+ * DestDir is non-empty, $CWD/<basename> otherwise. If
+ * DestFilename is NOT empty, DestDir is ignored and DestFilename
+ * is the absolute name to which the file should be downloaded.
+ */
+
+ pkgAcqFile(pkgAcquire *Owner, string URI, string Hash, unsigned long Size,
string Desc, string ShortDesc,
const string &DestDir="", const string &DestFilename="");
};
+/** @} */
+
#endif
diff --git a/apt-pkg/acquire-method.cc b/apt-pkg/acquire-method.cc
index 41b832f3b..bc29417f7 100644
--- a/apt-pkg/acquire-method.cc
+++ b/apt-pkg/acquire-method.cc
@@ -15,9 +15,6 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/acquire-method.h"
-#endif
#include <apt-pkg/acquire-method.h>
#include <apt-pkg/error.h>
#include <apt-pkg/configuration.h>
@@ -179,9 +176,14 @@ void pkgAcqMethod::URIDone(FetchResult &Res, FetchResult *Alt)
TimeRFC1123(Res.LastModified).c_str());
if (Res.MD5Sum.empty() == false)
+ {
End += snprintf(End,sizeof(S)-50 - (End - S),"MD5-Hash: %s\n",Res.MD5Sum.c_str());
+ End += snprintf(End,sizeof(S)-50 - (End - S),"MD5Sum-Hash: %s\n",Res.MD5Sum.c_str());
+ }
if (Res.SHA1Sum.empty() == false)
End += snprintf(End,sizeof(S)-50 - (End - S),"SHA1-Hash: %s\n",Res.SHA1Sum.c_str());
+ if (Res.SHA256Sum.empty() == false)
+ End += snprintf(End,sizeof(S)-50 - (End - S),"SHA256-Hash: %s\n",Res.SHA256Sum.c_str());
if (Res.GPGVOutput.size() > 0)
End += snprintf(End,sizeof(S)-50 - (End - S),"GPGVOutput:\n");
for (vector<string>::iterator I = Res.GPGVOutput.begin();
@@ -214,6 +216,9 @@ void pkgAcqMethod::URIDone(FetchResult &Res, FetchResult *Alt)
if (Alt->SHA1Sum.empty() == false)
End += snprintf(End,sizeof(S)-50 - (End - S),"Alt-SHA1-Hash: %s\n",
Alt->SHA1Sum.c_str());
+ if (Alt->SHA256Sum.empty() == false)
+ End += snprintf(End,sizeof(S)-50 - (End - S),"Alt-SHA256-Hash: %s\n",
+ Alt->SHA256Sum.c_str());
if (Alt->IMSHit == true)
strcat(End,"Alt-IMS-Hit: true\n");
@@ -458,5 +463,6 @@ void pkgAcqMethod::FetchResult::TakeHashes(Hashes &Hash)
{
MD5Sum = Hash.MD5.Result();
SHA1Sum = Hash.SHA1.Result();
+ SHA256Sum = Hash.SHA256.Result();
}
/*}}}*/
diff --git a/apt-pkg/acquire-method.h b/apt-pkg/acquire-method.h
index f46209d12..e02eab018 100644
--- a/apt-pkg/acquire-method.h
+++ b/apt-pkg/acquire-method.h
@@ -10,15 +10,19 @@
##################################################################### */
/*}}}*/
+
+/** \addtogroup acquire
+ * @{
+ *
+ * \file acquire-method.h
+ */
+
#ifndef PKGLIB_ACQUIRE_METHOD_H
#define PKGLIB_ACQUIRE_METHOD_H
#include <apt-pkg/configuration.h>
#include <apt-pkg/strutl.h>
-#ifdef __GNUG__
-#pragma interface "apt-pkg/acquire-method.h"
-#endif
class Hashes;
class pkgAcqMethod
@@ -39,6 +43,7 @@ class pkgAcqMethod
{
string MD5Sum;
string SHA1Sum;
+ string SHA256Sum;
vector<string> GPGVOutput;
time_t LastModified;
bool IMSHit;
@@ -86,4 +91,6 @@ class pkgAcqMethod
virtual ~pkgAcqMethod() {};
};
+/** @} */
+
#endif
diff --git a/apt-pkg/acquire-worker.cc b/apt-pkg/acquire-worker.cc
index d06024178..739c9e32c 100644
--- a/apt-pkg/acquire-worker.cc
+++ b/apt-pkg/acquire-worker.cc
@@ -12,9 +12,6 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/acquire-worker.h"
-#endif
#include <apt-pkg/acquire-worker.h>
#include <apt-pkg/acquire-item.h>
#include <apt-pkg/configuration.h>
@@ -270,8 +267,25 @@ bool pkgAcquire::Worker::RunMessages()
_error->Warning("Bizarre Error - File size is not what the server reported %s %lu",
LookupTag(Message,"Size","0").c_str(),TotalSize);
+ // see if there is a hash to verify
+ string RecivedHash;
+ HashString expectedHash(Owner->HashSum());
+ if(!expectedHash.empty())
+ {
+ string hashTag = expectedHash.HashType()+"-Hash";
+ string hashSum = LookupTag(Message, hashTag.c_str());
+ if(!hashSum.empty())
+ RecivedHash = expectedHash.HashType() + ":" + hashSum;
+ if(_config->FindB("Debug::pkgAcquire::Auth", false) == true)
+ {
+ clog << "201 URI Done: " << Owner->DescURI() << endl
+ << "RecivedHash: " << RecivedHash << endl
+ << "ExpectedHash: " << expectedHash.toStr()
+ << endl << endl;
+ }
+ }
Owner->Done(Message,atoi(LookupTag(Message,"Size","0").c_str()),
- LookupTag(Message,"MD5-Hash"),Config);
+ RecivedHash.c_str(), Config);
ItemDone();
// Log that we are done
@@ -307,6 +321,13 @@ bool pkgAcquire::Worker::RunMessages()
pkgAcquire::Item *Owner = Itm->Owner;
pkgAcquire::ItemDesc Desc = *Itm;
OwnerQ->ItemDone(Itm);
+
+ // set some status
+ if(LookupTag(Message,"FailReason") == "Timeout" ||
+ LookupTag(Message,"FailReason") == "TmpResolveFailure" ||
+ LookupTag(Message,"FailReason") == "ConnectionRefused")
+ Owner->Status = pkgAcquire::Item::StatTransientNetworkError;
+
Owner->Failed(Message,Config);
ItemDone();
diff --git a/apt-pkg/acquire-worker.h b/apt-pkg/acquire-worker.h
index 6e1952202..2942df69f 100644
--- a/apt-pkg/acquire-worker.h
+++ b/apt-pkg/acquire-worker.h
@@ -9,16 +9,38 @@
##################################################################### */
/*}}}*/
+
+/** \addtogroup acquire
+ * @{
+ *
+ * \file acquire-worker.h
+ */
+
#ifndef PKGLIB_ACQUIRE_WORKER_H
#define PKGLIB_ACQUIRE_WORKER_H
#include <apt-pkg/acquire.h>
-#ifdef __GNUG__
-#pragma interface "apt-pkg/acquire-worker.h"
-#endif
-// Interfacing to the method process
+/** \brief A fetch subprocess.
+ *
+ * A worker process is responsible for one stage of the fetch. This
+ * class encapsulates the communications protocol between the master
+ * process and the worker, from the master end.
+ *
+ * Each worker is intrinsically placed on two linked lists. The
+ * Queue list (maintained in the #NextQueue variable) is maintained
+ * by the pkgAcquire::Queue class; it represents the set of workers
+ * assigned to a particular queue. The Acquire list (maintained in
+ * the #NextAcquire variable) is maintained by the pkgAcquire class;
+ * it represents the set of active workers for a particular
+ * pkgAcquire object.
+ *
+ * \todo Like everything else in the Acquire system, this has way too
+ * many protected items.
+ *
+ * \sa pkgAcqMethod, pkgAcquire::Item, pkgAcquire
+ */
class pkgAcquire::Worker
{
friend class pkgAcquire;
@@ -26,64 +48,274 @@ class pkgAcquire::Worker
protected:
friend class Queue;
- /* Linked list starting at a Queue and a linked list starting
- at Acquire */
+ /** \brief The next link on the Queue list.
+ *
+ * \todo This is always NULL; is it just for future use?
+ */
Worker *NextQueue;
+
+ /** \brief The next link on the Acquire list. */
Worker *NextAcquire;
- // The access association
+ /** \brief The Queue with which this worker is associated. */
Queue *OwnerQ;
+
+ /** \brief The download progress indicator to which progress
+ * messages should be sent.
+ */
pkgAcquireStatus *Log;
+
+ /** \brief The configuration of this method. On startup, the
+ * target of this pointer is filled in with basic data about the
+ * method, as reported by the worker.
+ */
MethodConfig *Config;
+
+ /** \brief The access method to be used by this worker.
+ *
+ * \todo Doesn't this duplicate Config->Access?
+ */
string Access;
- // This is the subprocess IPC setup
+ /** \brief The PID of the subprocess. */
pid_t Process;
+
+ /** \brief A file descriptor connected to the standard output of
+ * the subprocess.
+ *
+ * Used to read messages and data from the subprocess.
+ */
int InFd;
+
+ /** \brief A file descriptor connected to the standard input of the
+ * subprocess.
+ *
+ * Used to send commands and configuration data to the subprocess.
+ */
int OutFd;
+
+ /** \brief Set to \b true if the worker is in a state in which it
+ * might generate data or command responses.
+ *
+ * \todo Is this right? It's a guess.
+ */
bool InReady;
+
+ /** \brief Set to \b true if the worker is in a state in which it
+ * is legal to send commands to it.
+ *
+ * \todo Is this right?
+ */
bool OutReady;
- // Various internal things
+ /** If \b true, debugging output will be sent to std::clog. */
bool Debug;
+
+ /** \brief The raw text values of messages received from the
+ * worker, in sequence.
+ */
vector<string> MessageQueue;
+
+ /** \brief Buffers pending writes to the subprocess.
+ *
+ * \todo Wouldn't a std::dequeue be more appropriate?
+ */
string OutQueue;
- // Private constructor helper
+ /** \brief Common code for the constructor.
+ *
+ * Initializes NextQueue and NextAcquire to NULL; Process, InFd,
+ * and OutFd to -1, OutReady and InReady to \b false, and Debug
+ * from _config.
+ */
void Construct();
- // Message handling things
+ /** \brief Retrieve any available messages from the subprocess.
+ *
+ * The messages are retrieved as in ::ReadMessages(), and
+ * MessageFailure() is invoked if an error occurs; in particular,
+ * if the pipe to the subprocess dies unexpectedly while a message
+ * is being read.
+ *
+ * \return \b true if the messages were successfully read, \b
+ * false otherwise.
+ */
bool ReadMessages();
+
+ /** \brief Parse and dispatch pending messages.
+ *
+ * This dispatches the message in a manner appropriate for its
+ * type.
+ *
+ * \todo Several message types lack separate handlers.
+ *
+ * \sa Capabilities(), SendConfiguration(), MediaChange()
+ */
bool RunMessages();
+
+ /** \brief Read and dispatch any pending messages from the
+ * subprocess.
+ *
+ * \return \b false if the subprocess died unexpectedly while a
+ * message was being transmitted.
+ */
bool InFdReady();
+
+ /** \brief Send any pending commands to the subprocess.
+ *
+ * This method will fail if there is no pending output.
+ *
+ * \return \b true if all commands were succeeded, \b false if an
+ * error occurred (in which case MethodFailure() will be invoked).
+ */
bool OutFdReady();
- // The message handlers
+ /** \brief Handle a 100 Capabilities response from the subprocess.
+ *
+ * \param Message the raw text of the message from the subprocess.
+ *
+ * The message will be parsed and its contents used to fill
+ * #Config. If #Config is NULL, this routine is a NOP.
+ *
+ * \return \b true.
+ */
bool Capabilities(string Message);
+
+ /** \brief Send a 601 Configuration message (containing the APT
+ * configuration) to the subprocess.
+ *
+ * The APT configuration will be send to the subprocess in a
+ * message of the following form:
+ *
+ * <pre>
+ * 601 Configuration
+ * Config-Item: Fully-Qualified-Item=Val
+ * Config-Item: Fully-Qualified-Item=Val
+ * ...
+ * </pre>
+ *
+ * \return \b true if the command was successfully sent, \b false
+ * otherwise.
+ */
bool SendConfiguration();
+
+ /** \brief Handle a 403 Media Change message.
+ *
+ * \param Message the raw text of the message; the Media field
+ * indicates what type of media should be changed, and the Drive
+ * field indicates where the media is located.
+ *
+ * Invokes pkgAcquireStatus::MediaChange(Media, Drive) to ask the
+ * user to swap disks; informs the subprocess of the result (via
+ * 603 Media Changed, with the Failed field set to \b true if the
+ * user cancelled the media change).
+ */
bool MediaChange(string Message);
+ /** \brief Invoked when the worked process dies unexpectedly.
+ *
+ * Waits for the subprocess to terminate and generates an error if
+ * it terminated abnormally, then closes and blanks out all file
+ * descriptors. Discards all pending messages from the
+ * subprocess.
+ *
+ * \return \b false.
+ */
bool MethodFailure();
+
+ /** \brief Invoked when a fetch job is completed, either
+ * successfully or unsuccessfully.
+ *
+ * Resets the status information for the worker process.
+ */
void ItemDone();
public:
- // The curent method state
+ /** \brief The queue entry that is currently being downloaded. */
pkgAcquire::Queue::QItem *CurrentItem;
+
+ /** \brief The most recent status string received from the
+ * subprocess.
+ */
string Status;
+
+ /** \brief How many bytes of the file have been downloaded. Zero
+ * if the current progress of the file cannot be determined.
+ */
unsigned long CurrentSize;
+
+ /** \brief The total number of bytes to be downloaded. Zero if the
+ * total size of the final is unknown.
+ */
unsigned long TotalSize;
+
+ /** \brief How much of the file was already downloaded prior to
+ * starting this worker.
+ */
unsigned long ResumePoint;
- // Load the method and do the startup
+ /** \brief Tell the subprocess to download the given item.
+ *
+ * \param Item the item to queue up.
+ * \return \b true if the item was successfully enqueued.
+ *
+ * Queues up a 600 URI Acquire message for the given item to be
+ * sent at the next possible moment. Does \e not flush the output
+ * queue.
+ */
bool QueueItem(pkgAcquire::Queue::QItem *Item);
+
+ /** \brief Start up the worker and fill in #Config.
+ *
+ * Reads the first message from the worker, which is assumed to be
+ * a 100 Capabilities message.
+ *
+ * \return \b true if all operations completed successfully.
+ */
bool Start();
+
+ /** \brief Update the worker statistics (CurrentSize, TotalSize,
+ * etc).
+ */
void Pulse();
+
+ /** \return The fetch method configuration. */
inline const MethodConfig *GetConf() const {return Config;};
-
+
+ /** \brief Create a new Worker to download files.
+ *
+ * \param OwnerQ The queue into which this worker should be
+ * placed.
+ *
+ * \param Config A location in which to store information about
+ * the fetch method.
+ *
+ * \param Log The download progress indicator that should be used
+ * to report the progress of this worker.
+ */
Worker(Queue *OwnerQ,MethodConfig *Config,pkgAcquireStatus *Log);
+
+ /** \brief Create a new Worker that should just retrieve
+ * information about the fetch method.
+ *
+ * Nothing in particular forces you to refrain from actually
+ * downloading stuff, but the various status callbacks won't be
+ * invoked.
+ *
+ * \param Config A location in which to store information about
+ * the fetch method.
+ */
Worker(MethodConfig *Config);
+
+ /** \brief Clean up this worker.
+ *
+ * Closes the file descriptors; if MethodConfig::NeedsCleanup is
+ * \b false, also rudely interrupts the worker with a SIGINT.
+ */
~Worker();
};
+/** @} */
+
#endif
diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc
index fff1b2b6a..6840ae120 100644
--- a/apt-pkg/acquire.cc
+++ b/apt-pkg/acquire.cc
@@ -13,9 +13,6 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/acquire.h"
-#endif
#include <apt-pkg/acquire.h>
#include <apt-pkg/acquire-item.h>
#include <apt-pkg/acquire-worker.h>
@@ -193,9 +190,9 @@ void pkgAcquire::Enqueue(ItemDesc &Item)
Item.Owner->Status = Item::StatIdle;
// Queue it into the named queue
- I->Enqueue(Item);
- ToFetch++;
-
+ if(I->Enqueue(Item))
+ ToFetch++;
+
// Some trace stuff
if (Debug == true)
{
@@ -549,11 +546,17 @@ pkgAcquire::Queue::~Queue()
// Queue::Enqueue - Queue an item to the queue /*{{{*/
// ---------------------------------------------------------------------
/* */
-void pkgAcquire::Queue::Enqueue(ItemDesc &Item)
+bool pkgAcquire::Queue::Enqueue(ItemDesc &Item)
{
QItem **I = &Items;
- for (; *I != 0; I = &(*I)->Next);
-
+ // move to the end of the queue and check for duplicates here
+ for (; *I != 0; I = &(*I)->Next)
+ if (Item.URI == (*I)->URI)
+ {
+ Item.Owner->Status = Item::StatDone;
+ return false;
+ }
+
// Create a new item
QItem *Itm = new QItem;
*Itm = Item;
@@ -563,6 +566,7 @@ void pkgAcquire::Queue::Enqueue(ItemDesc &Item)
Item.Owner->QueueCounter++;
if (Items->Next == 0)
Cycle();
+ return true;
}
/*}}}*/
// Queue::Dequeue - Remove an item from the queue /*{{{*/
@@ -615,7 +619,7 @@ bool pkgAcquire::Queue::Startup()
added other source retry to have cycle maintain a pipeline depth
on its own. */
if (Cnf->Pipeline == true)
- MaxPipeDepth = 10;
+ MaxPipeDepth = 1000;
else
MaxPipeDepth = 1;
}
diff --git a/apt-pkg/acquire.h b/apt-pkg/acquire.h
index 27bb3d363..1de6f5e44 100644
--- a/apt-pkg/acquire.h
+++ b/apt-pkg/acquire.h
@@ -29,6 +29,40 @@
##################################################################### */
/*}}}*/
+
+/** \defgroup acquire Acquire system
+ *
+ * \brief The Acquire system is responsible for retrieving files from
+ * local or remote URIs and postprocessing them (for instance,
+ * verifying their authenticity). The core class in this system is
+ * pkgAcquire, which is responsible for managing the download queues
+ * during the download. There is at least one download queue for
+ * each supported protocol; protocols such as http may provide one
+ * queue per host.
+ *
+ * Each file to download is represented by a subclass of
+ * pkgAcquire::Item. The files add themselves to the download
+ * queue(s) by providing their URI information to
+ * pkgAcquire::Item::QueueURI, which calls pkgAcquire::Enqueue.
+ *
+ * Once the system is set up, the Run method will spawn subprocesses
+ * to handle the enqueued URIs; the scheduler will then take items
+ * from the queues and feed them into the handlers until the queues
+ * are empty.
+ *
+ * \todo Acquire supports inserting an object into several queues at
+ * once, but it is not clear what its behavior in this case is, and
+ * no subclass of pkgAcquire::Item seems to actually use this
+ * capability.
+ */
+
+/** \addtogroup acquire
+ *
+ * @{
+ *
+ * \file acquire.h
+ */
+
#ifndef PKGLIB_ACQUIRE_H
#define PKGLIB_ACQUIRE_H
@@ -38,14 +72,20 @@
using std::vector;
using std::string;
-#ifdef __GNUG__
-#pragma interface "apt-pkg/acquire.h"
-#endif
#include <sys/time.h>
#include <unistd.h>
class pkgAcquireStatus;
+
+/** \brief The core download scheduler.
+ *
+ * This class represents an ongoing download. It manages the lists
+ * of active and pending downloads and handles setting up and tearing
+ * down download-related structures.
+ *
+ * \todo Why all the protected data items and methods?
+ */
class pkgAcquire
{
public:
@@ -60,97 +100,299 @@ class pkgAcquire
typedef vector<Item *>::iterator ItemIterator;
typedef vector<Item *>::const_iterator ItemCIterator;
-
+
protected:
- // List of items to fetch
+ /** \brief A list of items to download.
+ *
+ * This is built monotonically as items are created and only
+ * emptied when the download shuts down.
+ */
vector<Item *> Items;
- // List of active queues and fetched method configuration parameters
+ /** \brief The head of the list of active queues.
+ *
+ * \todo why a hand-managed list of queues instead of std::list or
+ * std::set?
+ */
Queue *Queues;
+
+ /** \brief The head of the list of active workers.
+ *
+ * \todo why a hand-managed list of workers instead of std::list
+ * or std::set?
+ */
Worker *Workers;
+
+ /** \brief The head of the list of acquire method configurations.
+ *
+ * Each protocol (http, ftp, gzip, etc) via which files can be
+ * fetched can have a representation in this list. The
+ * configuration data is filled in by parsing the 100 Capabilities
+ * string output by a method on startup (see
+ * pkgAcqMethod::pkgAcqMethod and pkgAcquire::GetConfig).
+ *
+ * \todo why a hand-managed config dictionary instead of std::map?
+ */
MethodConfig *Configs;
+
+ /** \brief The progress indicator for this download. */
pkgAcquireStatus *Log;
+
+ /** \brief The total size of the files which are to be fetched.
+ *
+ * This is not necessarily the total number of bytes to download
+ * when, e.g., download resumption and list updates via patches
+ * are taken into account.
+ */
unsigned long ToFetch;
- // Configurable parameters for the schedular
- enum {QueueHost,QueueAccess} QueueMode;
+ // Configurable parameters for the scheduler
+
+ /** \brief Represents the queuing strategy for remote URIs. */
+ enum QueueStrategy {
+ /** \brief Generate one queue for each protocol/host combination; downloads from
+ * multiple hosts can proceed in parallel.
+ */
+ QueueHost,
+ /** \brief Generate a single queue for each protocol; serialize
+ * downloads from multiple hosts.
+ */
+ QueueAccess} QueueMode;
+
+ /** \brief If \b true, debugging information will be dumped to std::clog. */
bool Debug;
+ /** \brief If \b true, a download is currently in progress. */
bool Running;
-
+
+ /** \brief Add the given item to the list of items. */
void Add(Item *Item);
+
+ /** \brief Remove the given item from the list of items. */
void Remove(Item *Item);
+
+ /** \brief Add the given worker to the list of workers. */
void Add(Worker *Work);
+
+ /** \brief Remove the given worker from the list of workers. */
void Remove(Worker *Work);
+ /** \brief Insert the given fetch request into the appropriate queue.
+ *
+ * \param Item The URI to download and the item to download it
+ * for. Copied by value into the queue; no reference to Item is
+ * retained.
+ */
void Enqueue(ItemDesc &Item);
+
+ /** \brief Remove all fetch requests for this item from all queues. */
void Dequeue(Item *Item);
+
+ /** \brief Determine the fetch method and queue of a URI.
+ *
+ * \param URI The URI to fetch.
+ *
+ * \param[out] Config A location in which to place the method via
+ * which the URI is to be fetched.
+ *
+ * \return the string-name of the queue in which a fetch request
+ * for the given URI should be placed.
+ */
string QueueName(string URI,MethodConfig const *&Config);
- // FDSET managers for derived classes
+ /** \brief Build up the set of file descriptors upon which select() should
+ * block.
+ *
+ * The default implementation inserts the file descriptors
+ * corresponding to active downloads.
+ *
+ * \param[out] Fd The largest file descriptor in the generated sets.
+ *
+ * \param[out] RSet The set of file descriptors that should be
+ * watched for input.
+ *
+ * \param[out] WSet The set of file descriptors that should be
+ * watched for output.
+ */
virtual void SetFds(int &Fd,fd_set *RSet,fd_set *WSet);
+
+ /** Handle input from and output to file descriptors which select()
+ * has determined are ready. The default implementation
+ * dispatches to all active downloads.
+ *
+ * \param RSet The set of file descriptors that are ready for
+ * input.
+ *
+ * \param WSet The set of file descriptors that are ready for
+ * output.
+ */
virtual void RunFds(fd_set *RSet,fd_set *WSet);
- // A queue calls this when it dequeues an item
+ /** \brief Check for idle queues with ready-to-fetch items.
+ *
+ * Called by pkgAcquire::Queue::Done each time an item is dequeued
+ * but remains on some queues; i.e., another queue should start
+ * fetching it.
+ */
void Bump();
public:
+ /** \brief Retrieve information about a fetch method by name.
+ *
+ * \param Access The name of the method to look up.
+ *
+ * \return the method whose name is Access, or \b NULL if no such method exists.
+ */
MethodConfig *GetConfig(string Access);
- enum RunResult {Continue,Failed,Cancelled};
+ /** \brief Provides information on how a download terminated. */
+ enum RunResult {
+ /** \brief All files were fetched successfully. */
+ Continue,
+
+ /** \brief Some files failed to download. */
+ Failed,
+
+ /** \brief The download was cancelled by the user (i.e., #Log's
+ * pkgAcquireStatus::Pulse() method returned \b false).
+ */
+ Cancelled};
+
+ /** \brief Download all the items that have been Add()ed to this
+ * download process.
+ *
+ * This method will block until the download completes, invoking
+ * methods on #Log to report on the progress of the download.
+ *
+ * \param PulseInterval The method pkgAcquireStatus::Pulse will be
+ * invoked on #Log at intervals of PulseInterval milliseconds.
+ *
+ * \return the result of the download.
+ */
+ RunResult Run(int PulseInterval=500000);
- RunResult Run(int PulseIntervall=500000);
+ /** \brief Remove all items from this download process, terminate
+ * all download workers, and empty all queues.
+ */
void Shutdown();
- // Simple iteration mechanism
+ /** \brief Get the first #Worker object.
+ *
+ * \return the first active worker in this download process.
+ */
inline Worker *WorkersBegin() {return Workers;};
+
+ /** \brief Advance to the next #Worker object.
+ *
+ * \return the worker immediately following I, or \b NULL if none
+ * exists.
+ */
Worker *WorkerStep(Worker *I);
+
+ /** \brief Get the head of the list of items. */
inline ItemIterator ItemsBegin() {return Items.begin();};
+
+ /** \brief Get the end iterator of the list of items. */
inline ItemIterator ItemsEnd() {return Items.end();};
// Iterate over queued Item URIs
class UriIterator;
+ /** \brief Get the head of the list of enqueued item URIs.
+ *
+ * This iterator will step over every element of every active
+ * queue.
+ */
UriIterator UriBegin();
+ /** \brief Get the end iterator of the list of enqueued item URIs. */
UriIterator UriEnd();
- // Cleans out the download dir
+ /** Deletes each entry in the given directory that is not being
+ * downloaded by this object. For instance, when downloading new
+ * list files, calling Clean() will delete the old ones.
+ *
+ * \param Dir The directory to be cleaned out.
+ *
+ * \return \b true if the directory exists and is readable.
+ */
bool Clean(string Dir);
- // Returns the size of the total download set
+ /** \return the total size in bytes of all the items included in
+ * this download.
+ */
double TotalNeeded();
+
+ /** \return the size in bytes of all non-local items included in
+ * this download.
+ */
double FetchNeeded();
+
+ /** \return the amount of data to be fetched that is already
+ * present on the filesystem.
+ */
double PartialPresent();
+ /** \brief Construct a new pkgAcquire.
+ *
+ * \param Log The progress indicator associated with this
+ * download, or \b NULL for none. This object is not owned by the
+ * download process and will not be deleted when the pkgAcquire
+ * object is destroyed. Naturally, it should live for at least as
+ * long as the pkgAcquire object does.
+ */
pkgAcquire(pkgAcquireStatus *Log = 0);
+
+ /** \brief Destroy this pkgAcquire object.
+ *
+ * Destroys all queue, method, and item objects associated with
+ * this download.
+ */
virtual ~pkgAcquire();
};
-// Description of an Item+URI
+/** \brief Represents a single download source from which an item
+ * should be downloaded.
+ *
+ * An item may have several assocated ItemDescs over its lifetime.
+ */
struct pkgAcquire::ItemDesc
{
+ /** \brief The URI from which to download this item. */
string URI;
+ /** brief A description of this item. */
string Description;
+ /** brief A shorter description of this item. */
string ShortDesc;
+ /** brief The underlying item which is to be downloaded. */
Item *Owner;
};
-// List of possible items queued for download.
+/** \brief A single download queue in a pkgAcquire object.
+ *
+ * \todo Why so many protected values?
+ */
class pkgAcquire::Queue
{
friend class pkgAcquire;
friend class pkgAcquire::UriIterator;
friend class pkgAcquire::Worker;
+
+ /** \brief The next queue in the pkgAcquire object's list of queues. */
Queue *Next;
protected:
- // Queued item
+ /** \brief A single item placed in this queue. */
struct QItem : pkgAcquire::ItemDesc
{
- QItem *Next;
+ /** \brief The next item in the queue. */
+ QItem *Next;
+ /** \brief The worker associated with this item, if any. */
pkgAcquire::Worker *Worker;
-
+
+ /** \brief Assign the ItemDesc portion of this QItem from
+ * another ItemDesc
+ */
void operator =(pkgAcquire::ItemDesc const &I)
{
URI = I.URI;
@@ -160,45 +402,145 @@ class pkgAcquire::Queue
};
};
- // Name of the queue
+ /** \brief The name of this queue. */
string Name;
- // Items queued into this queue
+ /** \brief The head of the list of items contained in this queue.
+ *
+ * \todo why a by-hand list instead of an STL structure?
+ */
QItem *Items;
+
+ /** \brief The head of the list of workers associated with this queue.
+ *
+ * \todo This is plural because support exists in Queue for
+ * multiple workers. However, it does not appear that there is
+ * any way to actually associate more than one worker with a
+ * queue.
+ *
+ * \todo Why not just use a std::set?
+ */
pkgAcquire::Worker *Workers;
+
+ /** \brief the download scheduler with which this queue is associated. */
pkgAcquire *Owner;
+
+ /** \brief The number of entries in this queue that are currently
+ * being downloaded.
+ */
signed long PipeDepth;
+
+ /** \brief The maximum number of entries that this queue will
+ * attempt to download at once.
+ */
unsigned long MaxPipeDepth;
public:
- // Put an item into this queue
- void Enqueue(ItemDesc &Item);
+ /** \brief Insert the given fetch request into this queue.
+ *
+ * \return \b true if the queuing was successful. May return
+ * \b false if the Item is already in the queue
+ */
+ bool Enqueue(ItemDesc &Item);
+
+ /** \brief Remove all fetch requests for the given item from this queue.
+ *
+ * \return \b true if at least one request was removed from the queue.
+ */
bool Dequeue(Item *Owner);
- // Find a Queued item
+ /** \brief Locate an item in this queue.
+ *
+ * \param URI A URI to match against.
+ * \param Owner A pkgAcquire::Worker to match against.
+ *
+ * \return the first item in the queue whose URI is #URI and that
+ * is being downloaded by #Owner.
+ */
QItem *FindItem(string URI,pkgAcquire::Worker *Owner);
+
+ /** Presumably this should start downloading an item?
+ *
+ * \todo Unimplemented. Implement it or remove?
+ */
bool ItemStart(QItem *Itm,unsigned long Size);
+
+ /** \brief Remove the given item from this queue and set its state
+ * to pkgAcquire::Item::StatDone.
+ *
+ * If this is the only queue containing the item, the item is also
+ * removed from the main queue by calling pkgAcquire::Dequeue.
+ *
+ * \param Itm The item to remove.
+ *
+ * \return \b true if no errors are encountered.
+ */
bool ItemDone(QItem *Itm);
+ /** \brief Start the worker process associated with this queue.
+ *
+ * If a worker process is already associated with this queue,
+ * this is equivalent to calling Cycle().
+ *
+ * \return \b true if the startup was successful.
+ */
bool Startup();
+
+ /** \brief Shut down the worker process associated with this queue.
+ *
+ * \param Final If \b true, then the process is stopped unconditionally.
+ * Otherwise, it is only stopped if it does not need cleanup
+ * as indicated by the pkgAcqMethod::NeedsCleanup member of
+ * its configuration.
+ *
+ * \return \b true.
+ */
bool Shutdown(bool Final);
+
+ /** \brief Send idle items to the worker process.
+ *
+ * Fills up the pipeline by inserting idle items into the worker's queue.
+ */
bool Cycle();
+
+ /** \brief Check for items that could be enqueued.
+ *
+ * Call this after an item placed in multiple queues has gone from
+ * the pkgAcquire::Item::StatFetching state to the
+ * pkgAcquire::Item::StatIdle state, to possibly refill an empty queue.
+ * This is an alias for Cycle().
+ *
+ * \todo Why both this and Cycle()? Are they expected to be
+ * different someday?
+ */
void Bump();
+ /** \brief Create a new Queue.
+ *
+ * \param Name The name of the new queue.
+ * \param Owner The download process that owns the new queue.
+ */
Queue(string Name,pkgAcquire *Owner);
+
+ /** Shut down all the worker processes associated with this queue
+ * and empty the queue.
+ */
~Queue();
};
+/** \brief Iterates over all the URIs being fetched by a pkgAcquire object. */
class pkgAcquire::UriIterator
{
+ /** The next queue to iterate over. */
pkgAcquire::Queue *CurQ;
+ /** The item that we currently point at. */
pkgAcquire::Queue::QItem *CurItem;
public:
- // Advance to the next item
inline void operator ++() {operator ++();};
+
void operator ++(int)
{
CurItem = CurItem->Next;
@@ -209,11 +551,14 @@ class pkgAcquire::UriIterator
}
};
- // Accessors
inline pkgAcquire::ItemDesc const *operator ->() const {return CurItem;};
inline bool operator !=(UriIterator const &rhs) const {return rhs.CurQ != CurQ || rhs.CurItem != CurItem;};
inline bool operator ==(UriIterator const &rhs) const {return rhs.CurQ == CurQ && rhs.CurItem == CurItem;};
+ /** \brief Create a new UriIterator.
+ *
+ * \param Q The queue over which this UriIterator should iterate.
+ */
UriIterator(pkgAcquire::Queue *Q) : CurQ(Q), CurItem(0)
{
while (CurItem == 0 && CurQ != 0)
@@ -224,61 +569,200 @@ class pkgAcquire::UriIterator
}
};
-// Configuration information from each method
+/** \brief Information about the properties of a single acquire method. */
struct pkgAcquire::MethodConfig
{
+ /** \brief The next link on the acquire method list.
+ *
+ * \todo Why not an STL container?
+ */
MethodConfig *Next;
+ /** \brief The name of this acquire method (e.g., http). */
string Access;
+ /** \brief The implementation version of this acquire method. */
string Version;
+
+ /** \brief If \b true, only one download queue should be created for this
+ * method.
+ */
bool SingleInstance;
+
+ /** \brief If \b true, this method supports pipelined downloading. */
bool Pipeline;
+
+ /** \brief If \b true, the worker process should send the entire
+ * APT configuration tree to the fetch subprocess when it starts
+ * up.
+ */
bool SendConfig;
+
+ /** \brief If \b true, this fetch method does not require network access;
+ * all files are to be acquired from the local disk.
+ */
bool LocalOnly;
+
+ /** \brief If \b true, the subprocess has to carry out some cleanup
+ * actions before shutting down.
+ *
+ * For instance, the cdrom method needs to unmount the CD after it
+ * finishes.
+ */
bool NeedsCleanup;
+
+ /** \brief If \b true, this fetch method acquires files from removable media. */
bool Removable;
+ /** \brief Set up the default method parameters.
+ *
+ * All fields are initialized to NULL, "", or \b false as
+ * appropriate.
+ */
MethodConfig();
};
+/** \brief A monitor object for downloads controlled by the pkgAcquire class.
+ *
+ * \todo Why protected members?
+ *
+ * \todo Should the double members be uint64_t?
+ */
class pkgAcquireStatus
{
protected:
+ /** \brief The last time at which this monitor object was updated. */
struct timeval Time;
+
+ /** \brief The time at which the download started. */
struct timeval StartTime;
+
+ /** \brief The number of bytes fetched as of the previous call to
+ * pkgAcquireStatus::Pulse, including local items.
+ */
double LastBytes;
+
+ /** \brief The current rate of download as of the most recent call
+ * to pkgAcquireStatus::Pulse, in bytes per second.
+ */
double CurrentCPS;
+
+ /** \brief The number of bytes fetched as of the most recent call
+ * to pkgAcquireStatus::Pulse, including local items.
+ */
double CurrentBytes;
+
+ /** \brief The total number of bytes that need to be fetched.
+ *
+ * \warning This member is inaccurate, as new items might be
+ * enqueued while the download is in progress!
+ */
double TotalBytes;
+
+ /** \brief The total number of bytes accounted for by items that
+ * were successfully fetched.
+ */
double FetchedBytes;
+
+ /** \brief The amount of time that has elapsed since the download
+ * started.
+ */
unsigned long ElapsedTime;
+
+ /** \brief The total number of items that need to be fetched.
+ *
+ * \warning This member is inaccurate, as new items might be
+ * enqueued while the download is in progress!
+ */
unsigned long TotalItems;
+
+ /** \brief The number of items that have been successfully downloaded. */
unsigned long CurrentItems;
public:
+ /** \brief If \b true, the download scheduler should call Pulse()
+ * at the next available opportunity.
+ */
bool Update;
+
+ /** \brief If \b true, extra Pulse() invocations will be performed.
+ *
+ * With this option set, Pulse() will be called every time that a
+ * download item starts downloading, finishes downloading, or
+ * terminates with an error.
+ */
bool MorePulses;
- // Called by items when they have finished a real download
+ /** \brief Invoked when a local or remote file has been completely fetched.
+ *
+ * \param Size The size of the file fetched.
+ *
+ * \param ResumePoint How much of the file was already fetched.
+ */
virtual void Fetched(unsigned long Size,unsigned long ResumePoint);
- // Called to change media
+ /** \brief Invoked when the user should be prompted to change the
+ * inserted removable media.
+ *
+ * This method should not return until the user has confirmed to
+ * the user interface that the media change is complete.
+ *
+ * \param Media The name of the media type that should be changed.
+ *
+ * \param Drive The identifying name of the drive whose media
+ * should be changed.
+ *
+ * \return \b true if the user confirms the media change, \b
+ * false if it is cancelled.
+ *
+ * \todo This is a horrible blocking monster; it should be CPSed
+ * with prejudice.
+ */
virtual bool MediaChange(string Media,string Drive) = 0;
- // Each of these is called by the workers when an event occures
+ /** \brief Invoked when an item is confirmed to be up-to-date.
+
+ * For instance, when an HTTP download is informed that the file on
+ * the server was not modified.
+ */
virtual void IMSHit(pkgAcquire::ItemDesc &/*Itm*/) {};
+
+ /** \brief Invoked when some of an item's data is fetched. */
virtual void Fetch(pkgAcquire::ItemDesc &/*Itm*/) {};
+
+ /** \brief Invoked when an item is successfully and completely fetched. */
virtual void Done(pkgAcquire::ItemDesc &/*Itm*/) {};
+
+ /** \brief Invoked when the process of fetching an item encounters
+ * a fatal error.
+ */
virtual void Fail(pkgAcquire::ItemDesc &/*Itm*/) {};
- virtual bool Pulse(pkgAcquire *Owner); // returns false on user cancel
+
+ /** \brief Periodically invoked while the Acquire process is underway.
+ *
+ * Subclasses should first call pkgAcquireStatus::Pulse(), then
+ * update their status output. The download process is blocked
+ * while Pulse() is being called.
+ *
+ * \return \b false if the user asked to cancel the whole Acquire process.
+ *
+ * \see pkgAcquire::Run
+ */
+ virtual bool Pulse(pkgAcquire *Owner);
+
+ /** \brief Invoked when the Acquire process starts running. */
virtual void Start();
+
+ /** \brief Invoked when the Acquire process stops running. */
virtual void Stop();
+ /** \brief Initialize all counters to 0 and the time to the current time. */
pkgAcquireStatus();
virtual ~pkgAcquireStatus() {};
};
+/** @} */
+
#endif
diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc
index 479927d65..158f9c258 100644
--- a/apt-pkg/algorithms.cc
+++ b/apt-pkg/algorithms.cc
@@ -14,16 +14,17 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/algorithms.h"
-#endif
#include <apt-pkg/algorithms.h>
#include <apt-pkg/error.h>
#include <apt-pkg/configuration.h>
+#include <apt-pkg/version.h>
#include <apt-pkg/sptr.h>
+
#include <apti18n.h>
-
+#include <sys/types.h>
+#include <cstdlib>
+#include <algorithm>
#include <iostream>
/*}}}*/
using namespace std;
@@ -100,6 +101,7 @@ bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/)
DepIterator End;
D.GlobOr(Start,End);
if (Start->Type == pkgCache::Dep::Conflicts ||
+ Start->Type == pkgCache::Dep::DpkgBreaks ||
Start->Type == pkgCache::Dep::Obsoletes ||
End->Type == pkgCache::Dep::PreDepends)
{
@@ -149,6 +151,8 @@ bool pkgSimulate::Configure(PkgIterator iPkg)
cout << " Obsoletes:" << D.TargetPkg().Name();
else if (D->Type == pkgCache::Dep::Conflicts)
cout << " Conflicts:" << D.TargetPkg().Name();
+ else if (D->Type == pkgCache::Dep::DpkgBreaks)
+ cout << " Breaks:" << D.TargetPkg().Name();
else
cout << " Depends:" << D.TargetPkg().Name();
}
@@ -220,6 +224,8 @@ void pkgSimulate::ShortBreaks()
the necessary calculations to deal with the problems. */
bool pkgApplyStatus(pkgDepCache &Cache)
{
+ pkgDepCache::ActionGroup group(Cache);
+
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
{
if (I->VersionList == 0)
@@ -230,13 +236,13 @@ bool pkgApplyStatus(pkgDepCache &Cache)
I->InstState == pkgCache::State::HoldReInstReq)
{
if (I->CurrentVer != 0 && I.CurrentVer().Downloadable() == true)
- Cache.MarkKeep(I);
+ Cache.MarkKeep(I, false, false);
else
{
// Is this right? Will dpkg choke on an upgrade?
if (Cache[I].CandidateVer != 0 &&
Cache[I].CandidateVerIter(Cache).Downloadable() == true)
- Cache.MarkInstall(I);
+ Cache.MarkInstall(I, false, 0, false);
else
return _error->Error(_("The package %s needs to be reinstalled, "
"but I can't find an archive for it."),I.Name());
@@ -251,14 +257,16 @@ bool pkgApplyStatus(pkgDepCache &Cache)
re-unpacked (probably) */
case pkgCache::State::UnPacked:
case pkgCache::State::HalfConfigured:
+ case pkgCache::State::TriggersAwaited:
+ case pkgCache::State::TriggersPending:
if ((I->CurrentVer != 0 && I.CurrentVer().Downloadable() == true) ||
I.State() != pkgCache::PkgIterator::NeedsUnpack)
- Cache.MarkKeep(I);
+ Cache.MarkKeep(I, false, false);
else
{
if (Cache[I].CandidateVer != 0 &&
Cache[I].CandidateVerIter(Cache).Downloadable() == true)
- Cache.MarkInstall(I);
+ Cache.MarkInstall(I, true, 0, false);
else
Cache.MarkDelete(I);
}
@@ -284,10 +292,12 @@ bool pkgApplyStatus(pkgDepCache &Cache)
on the result. */
bool pkgFixBroken(pkgDepCache &Cache)
{
+ pkgDepCache::ActionGroup group(Cache);
+
// Auto upgrade all broken packages
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
if (Cache[I].NowBroken() == true)
- Cache.MarkInstall(I,true);
+ Cache.MarkInstall(I, true, 0, false);
/* Fix packages that are in a NeedArchive state but don't have a
downloadable install version */
@@ -300,7 +310,7 @@ bool pkgFixBroken(pkgDepCache &Cache)
if (Cache[I].InstVerIter(Cache).Downloadable() == false)
continue;
- Cache.MarkInstall(I,true);
+ Cache.MarkInstall(I, true, 0, false);
}
pkgProblemResolver Fix(&Cache);
@@ -317,23 +327,25 @@ bool pkgFixBroken(pkgDepCache &Cache)
*/
bool pkgDistUpgrade(pkgDepCache &Cache)
{
+ pkgDepCache::ActionGroup group(Cache);
+
/* Auto upgrade all installed packages, this provides the basis
for the installation */
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
if (I->CurrentVer != 0)
- Cache.MarkInstall(I,true);
+ Cache.MarkInstall(I, true, 0, false);
/* Now, auto upgrade all essential packages - this ensures that
the essential packages are present and working */
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
- Cache.MarkInstall(I,true);
+ Cache.MarkInstall(I, true, 0, false);
/* We do it again over all previously installed packages to force
conflict resolution on them all. */
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
if (I->CurrentVer != 0)
- Cache.MarkInstall(I,false);
+ Cache.MarkInstall(I, false, 0, false);
pkgProblemResolver Fix(&Cache);
@@ -345,7 +357,7 @@ bool pkgDistUpgrade(pkgDepCache &Cache)
if (I->SelectedState == pkgCache::State::Hold)
{
Fix.Protect(I);
- Cache.MarkKeep(I);
+ Cache.MarkKeep(I, false, false);
}
}
}
@@ -360,6 +372,8 @@ bool pkgDistUpgrade(pkgDepCache &Cache)
to install packages not marked for install */
bool pkgAllUpgrade(pkgDepCache &Cache)
{
+ pkgDepCache::ActionGroup group(Cache);
+
pkgProblemResolver Fix(&Cache);
if (Cache.BrokenCount() != 0)
@@ -376,7 +390,7 @@ bool pkgAllUpgrade(pkgDepCache &Cache)
continue;
if (I->CurrentVer != 0 && Cache[I].InstallVer != 0)
- Cache.MarkInstall(I,false);
+ Cache.MarkInstall(I, false, 0, false);
}
return Fix.ResolveByKeep();
@@ -389,6 +403,8 @@ bool pkgAllUpgrade(pkgDepCache &Cache)
the package is restored. */
bool pkgMinimizeUpgrade(pkgDepCache &Cache)
{
+ pkgDepCache::ActionGroup group(Cache);
+
if (Cache.BrokenCount() != 0)
return false;
@@ -405,9 +421,9 @@ bool pkgMinimizeUpgrade(pkgDepCache &Cache)
continue;
// Keep it and see if that is OK
- Cache.MarkKeep(I);
+ Cache.MarkKeep(I, false, false);
if (Cache.BrokenCount() != 0)
- Cache.MarkInstall(I,false);
+ Cache.MarkInstall(I, false, 0, false);
else
{
// If keep didnt actually do anything then there was no change..
@@ -494,8 +510,10 @@ void pkgProblemResolver::MakeScores()
Score += PrioMap[Cache[I].InstVerIter(Cache)->Priority];
/* This helps to fix oddball problems with conflicting packages
- on the same level. We enhance the score of installed packages */
- if (I->CurrentVer != 0)
+ on the same level. We enhance the score of installed packages
+ if those are not obsolete
+ */
+ if (I->CurrentVer != 0 && Cache[I].CandidateVer != 0 && Cache[I].CandidateVerIter(Cache).Downloadable())
Score += 1;
}
@@ -565,6 +583,8 @@ void pkgProblemResolver::MakeScores()
installable */
bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
{
+ pkgDepCache::ActionGroup group(Cache);
+
if ((Flags[Pkg->ID] & Upgradable) == 0 || Cache[Pkg].Upgradable() == false)
return false;
if ((Flags[Pkg->ID] & Protected) == Protected)
@@ -573,7 +593,7 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
Flags[Pkg->ID] &= ~Upgradable;
bool WasKept = Cache[Pkg].Keep();
- Cache.MarkInstall(Pkg,false);
+ Cache.MarkInstall(Pkg, false, 0, false);
// This must be a virtual package or something like that.
if (Cache[Pkg].InstVerIter(Cache).end() == true)
@@ -637,6 +657,7 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
/* We let the algorithm deal with conflicts on its next iteration,
it is much smarter than us */
if (Start->Type == pkgCache::Dep::Conflicts ||
+ Start->Type == pkgCache::Dep::DpkgBreaks ||
Start->Type == pkgCache::Dep::Obsoletes)
break;
@@ -658,7 +679,7 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
if (Fail == true)
{
if (WasKept == true)
- Cache.MarkKeep(Pkg);
+ Cache.MarkKeep(Pkg, false, false);
else
Cache.MarkDelete(Pkg);
return false;
@@ -685,6 +706,8 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
upgrade packages to advoid problems. */
bool pkgProblemResolver::Resolve(bool BrokenFix)
{
+ pkgDepCache::ActionGroup group(Cache);
+
unsigned long Size = Cache.Head().PackageCount;
// Record which packages are marked for install
@@ -700,7 +723,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
{
if (Cache[I].InstBroken() == true && BrokenFix == true)
{
- Cache.MarkInstall(I,false);
+ Cache.MarkInstall(I, false, 0, false);
if (Cache[I].Install() == true)
Again = true;
}
@@ -766,14 +789,14 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
pkgCache::Version *OldVer = Cache[I].InstallVer;
Flags[I->ID] &= ReInstateTried;
- Cache.MarkInstall(I,false);
+ Cache.MarkInstall(I, false, 0, false);
if (Cache[I].InstBroken() == true ||
OldBreaks < Cache.BrokenCount())
{
if (OldVer == 0)
Cache.MarkDelete(I);
else
- Cache.MarkKeep(I);
+ Cache.MarkKeep(I, false, false);
}
else
if (Debug == true)
@@ -784,7 +807,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
continue;
if (Debug == true)
- cout << "Investigating " << I.Name() << endl;
+ clog << "Investigating " << I.Name() << endl;
// Isolate the problem dependency
PackageKill KillList[100];
@@ -818,7 +841,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
{
if (Debug == true)
clog << " Or group keep for " << I.Name() << endl;
- Cache.MarkKeep(I);
+ Cache.MarkKeep(I, false, false);
Change = true;
}
}
@@ -839,7 +862,12 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
OldEnd = LEnd;
}
else
+ {
Start++;
+ // We only worry about critical deps.
+ if (Start.IsCritical() != true)
+ continue;
+ }
// Dep is ok
if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
@@ -857,6 +885,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
SPtrArray<pkgCache::Version *> VList = Start.AllTargets();
if (*VList == 0 && (Flags[I->ID] & Protected) != Protected &&
Start->Type != pkgCache::Dep::Conflicts &&
+ Start->Type != pkgCache::Dep::DpkgBreaks &&
Start->Type != pkgCache::Dep::Obsoletes &&
Cache[I].NowBroken() == false)
{
@@ -868,7 +897,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
}
Change = true;
- Cache.MarkKeep(I);
+ Cache.MarkKeep(I, false, false);
break;
}
@@ -887,6 +916,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
if (Scores[I->ID] <= Scores[Pkg->ID] ||
((Cache[Start] & pkgDepCache::DepNow) == 0 &&
End->Type != pkgCache::Dep::Conflicts &&
+ End->Type != pkgCache::Dep::DpkgBreaks &&
End->Type != pkgCache::Dep::Obsoletes))
{
// Try a little harder to fix protected packages..
@@ -905,7 +935,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
/* See if a keep will do, unless the package is protected,
then installing it will be necessary */
bool Installed = Cache[I].Install();
- Cache.MarkKeep(I);
+ Cache.MarkKeep(I, false, false);
if (Cache[I].InstBroken() == false)
{
// Unwind operation will be keep now
@@ -914,7 +944,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
// Restore
if (InOr == true && Installed == true)
- Cache.MarkInstall(I,false);
+ Cache.MarkInstall(I, false, 0, false);
if (Debug == true)
clog << " Holding Back " << I.Name() << " rather than change " << Start.TargetPkg().Name() << endl;
@@ -952,7 +982,22 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
(Start->Type == pkgCache::Dep::Conflicts ||
Start->Type == pkgCache::Dep::Obsoletes))
continue;
-
+
+ if (Start->Type == pkgCache::Dep::DpkgBreaks)
+ {
+ /* Would it help if we upgraded? */
+ if (Cache[End] & pkgDepCache::DepGCVer) {
+ if (Debug)
+ clog << " Upgrading " << Pkg.Name() << " due to Breaks field in " << I.Name() << endl;
+ Cache.MarkInstall(Pkg, false, 0, false);
+ continue;
+ }
+ if (Debug)
+ clog << " Will not break " << Pkg.Name() << " as stated in Breaks field in " << I.Name() <<endl;
+ Cache.MarkKeep(I, false, false);
+ continue;
+ }
+
// Skip adding to the kill list if it is protected
if ((Flags[Pkg->ID] & Protected) != 0)
continue;
@@ -973,6 +1018,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
// Hm, nothing can possibly satisify this dep. Nuke it.
if (VList[0] == 0 &&
Start->Type != pkgCache::Dep::Conflicts &&
+ Start->Type != pkgCache::Dep::DpkgBreaks &&
Start->Type != pkgCache::Dep::Obsoletes &&
(Flags[I->ID] & Protected) != Protected)
{
@@ -986,7 +1032,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
// Restore
if (InOr == true && Installed == true)
- Cache.MarkInstall(I,false);
+ Cache.MarkInstall(I, false, 0, false);
if (Debug == true)
clog << " Holding Back " << I.Name() << " because I can't find " << Start.TargetPkg().Name() << endl;
@@ -1031,7 +1077,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
{
if (Debug == true)
clog << " Fixing " << I.Name() << " via keep of " << J->Pkg.Name() << endl;
- Cache.MarkKeep(J->Pkg);
+ Cache.MarkKeep(J->Pkg, false, false);
}
if (Counter > 1)
@@ -1061,6 +1107,20 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
return _error->Error(_("Unable to correct problems, you have held broken packages."));
}
+ // set the auto-flags (mvo: I'm not sure if we _really_ need this, but
+ // I didn't managed
+ pkgCache::PkgIterator I = Cache.PkgBegin();
+ for (;I.end() != true; I++) {
+ if (Cache[I].NewInstall() && !(Flags[I->ID] & PreInstalled)) {
+ if(_config->FindI("Debug::pkgAutoRemove",false)) {
+ std::clog << "Resolve installed new pkg: " << I.Name()
+ << " (now marking it as auto)" << std::endl;
+ }
+ Cache[I].Flags |= pkgCache::Flag::Auto;
+ }
+ }
+
+
return true;
}
/*}}}*/
@@ -1071,6 +1131,8 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
system was non-broken previously. */
bool pkgProblemResolver::ResolveByKeep()
{
+ pkgDepCache::ActionGroup group(Cache);
+
unsigned long Size = Cache.Head().PackageCount;
if (Debug == true)
@@ -1104,7 +1166,7 @@ bool pkgProblemResolver::ResolveByKeep()
{
if (Debug == true)
clog << "Keeping package " << I.Name() << endl;
- Cache.MarkKeep(I);
+ Cache.MarkKeep(I, false, false);
if (Cache[I].InstBroken() == false)
{
K = PList - 1;
@@ -1152,7 +1214,7 @@ bool pkgProblemResolver::ResolveByKeep()
{
if (Debug == true)
clog << " Keeping Package " << Pkg.Name() << " due to dep" << endl;
- Cache.MarkKeep(Pkg);
+ Cache.MarkKeep(Pkg, false, false);
}
if (Cache[I].InstBroken() == false)
@@ -1189,14 +1251,21 @@ bool pkgProblemResolver::ResolveByKeep()
/* This is used to make sure protected packages are installed */
void pkgProblemResolver::InstallProtect()
{
+ pkgDepCache::ActionGroup group(Cache);
+
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
{
if ((Flags[I->ID] & Protected) == Protected)
{
if ((Flags[I->ID] & ToRemove) == ToRemove)
Cache.MarkDelete(I);
- else
- Cache.MarkInstall(I,false);
+ else
+ {
+ // preserve the information whether the package was auto
+ // or manually installed
+ bool autoInst = (Cache[I].Flags & pkgCache::Flag::Auto);
+ Cache.MarkInstall(I, false, 0, !autoInst);
+ }
}
}
}
@@ -1232,3 +1301,4 @@ void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List)
qsort(List,Count,sizeof(*List),PrioComp);
}
/*}}}*/
+
diff --git a/apt-pkg/algorithms.h b/apt-pkg/algorithms.h
index b95218061..b72874d8e 100644
--- a/apt-pkg/algorithms.h
+++ b/apt-pkg/algorithms.h
@@ -30,9 +30,6 @@
#ifndef PKGLIB_ALGORITHMS_H
#define PKGLIB_ALGORITHMS_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/algorithms.h"
-#endif
#include <apt-pkg/packagemanager.h>
#include <apt-pkg/depcache.h>
diff --git a/apt-pkg/cachefile.cc b/apt-pkg/cachefile.cc
index 8b8e6dc98..4c2c56893 100644
--- a/apt-pkg/cachefile.cc
+++ b/apt-pkg/cachefile.cc
@@ -12,10 +12,6 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/cachefile.h"
-#endif
-
#include <apt-pkg/cachefile.h>
#include <apt-pkg/error.h>
#include <apt-pkg/sourcelist.h>
@@ -115,7 +111,9 @@ bool pkgCacheFile::Open(OpProgress &Progress,bool WithLock)
// CacheFile::ListUpdate - update the cache files /*{{{*/
// ---------------------------------------------------------------------
-/* */
+/* This is a simple wrapper to update the cache. it will fetch stuff
+ * from the network (or any other sources defined in sources.list)
+ */
bool pkgCacheFile::ListUpdate(pkgAcquireStatus &Stat, pkgSourceList &List)
{
pkgAcquire Fetcher(&Stat);
@@ -123,43 +121,58 @@ bool pkgCacheFile::ListUpdate(pkgAcquireStatus &Stat, pkgSourceList &List)
// Populate it with the source selection
if (List.GetIndexes(&Fetcher) == false)
return false;
-
+
// Run scripts
RunScripts("APT::Update::Pre-Invoke");
-
+
// Run it
if (Fetcher.Run() == pkgAcquire::Failed)
return false;
bool Failed = false;
- for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
+ bool TransientNetworkFailure = false;
+ for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin();
+ I != Fetcher.ItemsEnd(); I++)
{
if ((*I)->Status == pkgAcquire::Item::StatDone)
continue;
(*I)->Finished();
-
- _error->Warning(_("Failed to fetch %s %s\n"),
- (*I)->DescURI().c_str(),
- (*I)->ErrorText.c_str());
+
+ fprintf(stderr,_("Failed to fetch %s %s\n"),(*I)->DescURI().c_str(),
+ (*I)->ErrorText.c_str());
+
+ if ((*I)->Status == pkgAcquire::Item::StatTransientNetworkError)
+ {
+ TransientNetworkFailure = true;
+ continue;
+ }
+
Failed = true;
}
-
- // Clean out any old list files (if it was not a failure)
+
+ // Clean out any old list files
// Keep "APT::Get::List-Cleanup" name for compatibility, but
// this is really a global option for the APT library now
- if (!Failed && (_config->FindB("APT::Get::List-Cleanup",true) == true ||
- _config->FindB("APT::List-Cleanup",true) == true))
+ if (!TransientNetworkFailure && !Failed &&
+ (_config->FindB("APT::Get::List-Cleanup",true) == true ||
+ _config->FindB("APT::List-Cleanup",true) == true))
{
if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false ||
Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") == false)
+ // something went wrong with the clean
return false;
}
+
+ if (TransientNetworkFailure == true)
+ _error->Warning(_("Some index files failed to download, they have been ignored, or old ones used instead."));
+ else if (Failed == true)
+ return _error->Error(_("Some index files failed to download, they have been ignored, or old ones used instead."));
- // Run the scripts
- RunScripts("APT::Update::Post-Invoke");
- return (Failed == false);
+ // Run the scripts if all was fine
+ RunScripts("APT::Update::Post-Invoke");
+ return true;
}
/*}}}*/
diff --git a/apt-pkg/cachefile.h b/apt-pkg/cachefile.h
index 366e3576f..02c6188a7 100644
--- a/apt-pkg/cachefile.h
+++ b/apt-pkg/cachefile.h
@@ -17,9 +17,6 @@
#ifndef PKGLIB_CACHEFILE_H
#define PKGLIB_CACHEFILE_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/cachefile.h"
-#endif
#include <apt-pkg/depcache.h>
#include <apt-pkg/acquire.h>
diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h
index 2b326bd65..08eafca0f 100644
--- a/apt-pkg/cacheiterators.h
+++ b/apt-pkg/cacheiterators.h
@@ -31,9 +31,6 @@
#ifndef PKGLIB_CACHEITERATORS_H
#define PKGLIB_CACHEITERATORS_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/cacheiterators.h"
-#endif
// Package Iterator
class pkgCache::PkgIterator
@@ -99,7 +96,7 @@ class pkgCache::VerIterator
{
Version *Ver;
pkgCache *Owner;
-
+
void _dummy();
public:
@@ -128,6 +125,8 @@ class pkgCache::VerIterator
inline const char *Section() const {return Ver->Section == 0?0:Owner->StrP + Ver->Section;};
inline const char *Arch() const {return Ver->Arch == 0?0:Owner->StrP + Ver->Arch;};
inline PkgIterator ParentPkg() const {return PkgIterator(*Owner,Owner->PkgP + Ver->ParentPkg);};
+ inline DescIterator DescriptionList() const;
+ DescIterator TranslatedDescription() const;
inline DepIterator DependsList() const;
inline PrvIterator ProvidesList() const;
inline VerFileIterator FileList() const;
@@ -148,6 +147,50 @@ class pkgCache::VerIterator
};
};
+// Description Iterator
+class pkgCache::DescIterator
+{
+ Description *Desc;
+ pkgCache *Owner;
+
+ void _dummy();
+
+ public:
+
+ // Iteration
+ void operator ++(int) {if (Desc != Owner->DescP) Desc = Owner->DescP + Desc->NextDesc;};
+ inline void operator ++() {operator ++(0);};
+ inline bool end() const {return Desc == Owner->DescP?true:false;};
+ inline void operator =(const DescIterator &B) {Desc = B.Desc; Owner = B.Owner;};
+
+ // Comparison
+ inline bool operator ==(const DescIterator &B) const {return Desc == B.Desc;};
+ inline bool operator !=(const DescIterator &B) const {return Desc != B.Desc;};
+ int CompareDesc(const DescIterator &B) const;
+
+ // Accessors
+ inline Description *operator ->() {return Desc;};
+ inline Description const *operator ->() const {return Desc;};
+ inline Description &operator *() {return *Desc;};
+ inline Description const &operator *() const {return *Desc;};
+ inline operator Description *() {return Desc == Owner->DescP?0:Desc;};
+ inline operator Description const *() const {return Desc == Owner->DescP?0:Desc;};
+ inline pkgCache *Cache() {return Owner;};
+
+ inline const char *LanguageCode() const {return Owner->StrP + Desc->language_code;};
+ inline const char *md5() const {return Owner->StrP + Desc->md5sum;};
+ inline DescFileIterator FileList() const;
+ inline unsigned long Index() const {return Desc - Owner->DescP;};
+
+ inline DescIterator() : Desc(0), Owner(0) {};
+ inline DescIterator(pkgCache &Owner,Description *Trg = 0) : Desc(Trg),
+ Owner(&Owner)
+ {
+ if (Desc == 0)
+ Desc = Owner.DescP;
+ };
+};
+
// Dependency iterator
class pkgCache::DepIterator
{
@@ -338,6 +381,38 @@ class pkgCache::VerFileIterator
inline VerFileIterator(pkgCache &Owner,VerFile *Trg) : Owner(&Owner), FileP(Trg) {};
};
+// Description File
+class pkgCache::DescFileIterator
+{
+ pkgCache *Owner;
+ DescFile *FileP;
+
+ public:
+
+ // Iteration
+ void operator ++(int) {if (FileP != Owner->DescFileP) FileP = Owner->DescFileP + FileP->NextFile;};
+ inline void operator ++() {operator ++(0);};
+ inline bool end() const {return FileP == Owner->DescFileP?true:false;};
+
+ // Comparison
+ inline bool operator ==(const DescFileIterator &B) const {return FileP == B.FileP;};
+ inline bool operator !=(const DescFileIterator &B) const {return FileP != B.FileP;};
+
+ // Accessors
+ inline DescFile *operator ->() {return FileP;};
+ inline DescFile const *operator ->() const {return FileP;};
+ inline DescFile const &operator *() const {return *FileP;};
+ inline operator DescFile *() {return FileP == Owner->DescFileP?0:FileP;};
+ inline operator DescFile const *() const {return FileP == Owner->DescFileP?0:FileP;};
+ inline pkgCache *Cache() {return Owner;};
+
+ inline PkgFileIterator File() const {return PkgFileIterator(*Owner,FileP->File + Owner->PkgFileP);};
+ inline unsigned long Index() const {return FileP - Owner->DescFileP;};
+
+ inline DescFileIterator() : Owner(0), FileP(0) {};
+ inline DescFileIterator(pkgCache &Owner,DescFile *Trg) : Owner(&Owner), FileP(Trg) {};
+};
+
// Inlined Begin functions cant be in the class because of order problems
inline pkgCache::VerIterator pkgCache::PkgIterator::VersionList() const
{return VerIterator(*Owner,Owner->VerP + Pkg->VersionList);};
@@ -347,11 +422,15 @@ inline pkgCache::DepIterator pkgCache::PkgIterator::RevDependsList() const
{return DepIterator(*Owner,Owner->DepP + Pkg->RevDepends,Pkg);};
inline pkgCache::PrvIterator pkgCache::PkgIterator::ProvidesList() const
{return PrvIterator(*Owner,Owner->ProvideP + Pkg->ProvidesList,Pkg);};
+inline pkgCache::DescIterator pkgCache::VerIterator::DescriptionList() const
+ {return DescIterator(*Owner,Owner->DescP + Ver->DescriptionList);};
inline pkgCache::PrvIterator pkgCache::VerIterator::ProvidesList() const
{return PrvIterator(*Owner,Owner->ProvideP + Ver->ProvidesList,Ver);};
inline pkgCache::DepIterator pkgCache::VerIterator::DependsList() const
{return DepIterator(*Owner,Owner->DepP + Ver->DependsList,Ver);};
inline pkgCache::VerFileIterator pkgCache::VerIterator::FileList() const
{return VerFileIterator(*Owner,Owner->VerFileP + Ver->FileList);};
+inline pkgCache::DescFileIterator pkgCache::DescIterator::FileList() const
+ {return DescFileIterator(*Owner,Owner->DescFileP + Desc->FileList);};
#endif
diff --git a/apt-pkg/cdrom.cc b/apt-pkg/cdrom.cc
index ce1beb39b..0cbdc178f 100644
--- a/apt-pkg/cdrom.cc
+++ b/apt-pkg/cdrom.cc
@@ -1,9 +1,6 @@
/*
*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/cdrom.h"
-#endif
#include<apt-pkg/init.h>
#include<apt-pkg/error.h>
#include<apt-pkg/cdromutl.h>
@@ -18,6 +15,7 @@
#include <dirent.h>
#include <unistd.h>
#include <stdio.h>
+#include <algorithm>
#include "indexcopy.h"
@@ -30,12 +28,16 @@ using namespace std;
search that short circuits when it his a package file in the dir.
This speeds it up greatly as the majority of the size is in the
binary-* sub dirs. */
-bool pkgCdrom::FindPackages(string CD,vector<string> &List,
- vector<string> &SList, vector<string> &SigList,
+bool pkgCdrom::FindPackages(string CD,
+ vector<string> &List,
+ vector<string> &SList,
+ vector<string> &SigList,
+ vector<string> &TransList,
string &InfoDir, pkgCdromStatus *log,
unsigned int Depth)
{
static ino_t Inodes[9];
+ DIR *D;
// if we have a look we "pulse" now
if(log)
@@ -90,8 +92,28 @@ bool pkgCdrom::FindPackages(string CD,vector<string> &List,
if (_config->FindB("APT::CDROM::Thorough",false) == false)
return true;
}
+
+ // see if we find translatin indexes
+ if (stat("i18n",&Buf) == 0)
+ {
+ D = opendir("i18n");
+ for (struct dirent *Dir = readdir(D); Dir != 0; Dir = readdir(D))
+ {
+ if(strstr(Dir->d_name,"Translation") != NULL)
+ {
+ if (_config->FindB("Debug::aptcdrom",false) == true)
+ std::clog << "found translations: " << Dir->d_name << "\n";
+ string file = Dir->d_name;
+ if(file.substr(file.size()-3,file.size()) == ".gz")
+ file = file.substr(0,file.size()-3);
+ TransList.push_back(CD+"i18n/"+ file);
+ }
+ }
+ closedir(D);
+ }
+
- DIR *D = opendir(".");
+ D = opendir(".");
if (D == 0)
return _error->Errno("opendir","Unable to read %s",CD.c_str());
@@ -127,7 +149,7 @@ bool pkgCdrom::FindPackages(string CD,vector<string> &List,
Inodes[Depth] = Buf.st_ino;
// Descend
- if (FindPackages(CD + Dir->d_name,List,SList,SigList,InfoDir,log,Depth+1) == false)
+ if (FindPackages(CD + Dir->d_name,List,SList,SigList,TransList,InfoDir,log,Depth+1) == false)
break;
if (chdir(CD.c_str()) != 0)
@@ -538,10 +560,17 @@ bool pkgCdrom::Ident(string &ident, pkgCdromStatus *log)
}
if(log) {
msg.str("");
- ioprintf(msg, _("Stored label: %s \n"),
- Database.Find("CD::"+ident).c_str());
+ ioprintf(msg, _("Stored label: %s\n"),
+ Database.Find("CD::"+ident).c_str());
log->Update(msg.str());
}
+
+ // Unmount and finish
+ if (_config->FindB("APT::CDROM::NoMount",false) == false) {
+ log->Update(_("Unmounting CD-ROM...\n"), STEP_LAST);
+ UnmountCdrom(CDROM);
+ }
+
return true;
}
@@ -612,9 +641,10 @@ bool pkgCdrom::Add(pkgCdromStatus *log)
vector<string> List;
vector<string> SourceList;
vector<string> SigList;
+ vector<string> TransList;
string StartDir = SafeGetCWD();
string InfoDir;
- if (FindPackages(CDROM,List,SourceList, SigList,InfoDir,log) == false)
+ if (FindPackages(CDROM,List,SourceList, SigList,TransList,InfoDir,log) == false)
{
log->Update("\n");
return false;
@@ -642,17 +672,20 @@ bool pkgCdrom::Add(pkgCdromStatus *log)
DropRepeats(List,"Packages");
DropRepeats(SourceList,"Sources");
DropRepeats(SigList,"Release.gpg");
+ DropRepeats(TransList,"");
if(log) {
msg.str("");
- ioprintf(msg, _("Found %i package indexes, %i source indexes and "
- "%i signatures\n"),
- List.size(), SourceList.size(), SigList.size());
+ ioprintf(msg, _("Found %u package indexes, %u source indexes, "
+ "%u translation indexes and %u signatures\n"),
+ List.size(), SourceList.size(), TransList.size(),
+ SigList.size());
log->Update(msg.str(), STEP_SCAN);
}
if (List.size() == 0 && SourceList.size() == 0)
{
- UnmountCdrom(CDROM);
+ if (_config->FindB("APT::CDROM::NoMount",false) == false)
+ UnmountCdrom(CDROM);
return _error->Error("Unable to locate any package files, perhaps this is not a Debian Disc");
}
@@ -679,7 +712,7 @@ bool pkgCdrom::Add(pkgCdromStatus *log)
if(log) {
msg.str("");
- ioprintf(msg, "Found label '%s'\n", Name.c_str());
+ ioprintf(msg, _("Found label '%s'\n"), Name.c_str());
log->Update(msg.str());
}
Database.Set("CD::" + ID + "::Label",Name);
@@ -691,7 +724,8 @@ bool pkgCdrom::Add(pkgCdromStatus *log)
{
if(!log)
{
- UnmountCdrom(CDROM);
+ if (_config->FindB("APT::CDROM::NoMount",false) == false)
+ UnmountCdrom(CDROM);
return _error->Error("No disc name found and no way to ask for it");
}
@@ -736,8 +770,10 @@ bool pkgCdrom::Add(pkgCdromStatus *log)
// Copy the package files to the state directory
PackageCopy Copy;
SourceCopy SrcCopy;
+ TranslationsCopy TransCopy;
if (Copy.CopyPackages(CDROM,Name,List, log) == false ||
- SrcCopy.CopyPackages(CDROM,Name,SourceList, log) == false)
+ SrcCopy.CopyPackages(CDROM,Name,SourceList, log) == false ||
+ TransCopy.CopyTranslations(CDROM,Name,TransList, log) == false)
return false;
// reduce the List so that it takes less space in sources.list
@@ -767,7 +803,8 @@ bool pkgCdrom::Add(pkgCdromStatus *log)
string::size_type Space = (*I).find(' ');
if (Space == string::npos)
{
- UnmountCdrom(CDROM);
+ if (_config->FindB("APT::CDROM::NoMount",false) == false)
+ UnmountCdrom(CDROM);
return _error->Error("Internal error");
}
@@ -784,7 +821,8 @@ bool pkgCdrom::Add(pkgCdromStatus *log)
string::size_type Space = (*I).find(' ');
if (Space == string::npos)
{
- UnmountCdrom(CDROM);
+ if (_config->FindB("APT::CDROM::NoMount",false) == false)
+ UnmountCdrom(CDROM);
return _error->Error("Internal error");
}
@@ -800,7 +838,7 @@ bool pkgCdrom::Add(pkgCdromStatus *log)
// Unmount and finish
if (_config->FindB("APT::CDROM::NoMount",false) == false) {
- log->Update(_("Unmounting CD-ROM..."), STEP_LAST);
+ log->Update(_("Unmounting CD-ROM...\n"), STEP_LAST);
UnmountCdrom(CDROM);
}
diff --git a/apt-pkg/cdrom.h b/apt-pkg/cdrom.h
index 085eb64e2..68d61c098 100644
--- a/apt-pkg/cdrom.h
+++ b/apt-pkg/cdrom.h
@@ -5,9 +5,6 @@
#include<string>
#include<vector>
-#ifdef __GNUG__
-#pragma interface "apt-pkg/cdrom.h"
-#endif
using namespace std;
@@ -50,8 +47,11 @@ class pkgCdrom
};
- bool FindPackages(string CD,vector<string> &List,
- vector<string> &SList, vector<string> &SigList,
+ bool FindPackages(string CD,
+ vector<string> &List,
+ vector<string> &SList,
+ vector<string> &SigList,
+ vector<string> &TransList,
string &InfoDir, pkgCdromStatus *log,
unsigned int Depth = 0);
bool DropBinaryArch(vector<string> &List);
diff --git a/apt-pkg/clean.cc b/apt-pkg/clean.cc
index 0d623d862..3fa67e8e6 100644
--- a/apt-pkg/clean.cc
+++ b/apt-pkg/clean.cc
@@ -8,10 +8,6 @@
##################################################################### */
/*}}}*/
// Includes /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/clean.h"
-#endif
-
#include <apt-pkg/clean.h>
#include <apt-pkg/strutl.h>
#include <apt-pkg/error.h>
diff --git a/apt-pkg/clean.h b/apt-pkg/clean.h
index 43164e250..2aee2bf54 100644
--- a/apt-pkg/clean.h
+++ b/apt-pkg/clean.h
@@ -10,9 +10,6 @@
#ifndef APTPKG_CLEAN_H
#define APTPKG_CLEAN_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/clean.h"
-#endif
#include <apt-pkg/pkgcache.h>
diff --git a/apt-pkg/contrib/cdromutl.cc b/apt-pkg/contrib/cdromutl.cc
index ab170ec5a..6f00e1451 100644
--- a/apt-pkg/contrib/cdromutl.cc
+++ b/apt-pkg/contrib/cdromutl.cc
@@ -10,9 +10,6 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/cdromutl.h"
-#endif
#include <apt-pkg/cdromutl.h>
#include <apt-pkg/error.h>
#include <apt-pkg/md5.h>
diff --git a/apt-pkg/contrib/cdromutl.h b/apt-pkg/contrib/cdromutl.h
index 3180a03c7..f24bb8c70 100644
--- a/apt-pkg/contrib/cdromutl.h
+++ b/apt-pkg/contrib/cdromutl.h
@@ -8,18 +8,15 @@
##################################################################### */
/*}}}*/
#ifndef PKGLIB_CDROMUTL_H
-#define PKGLIB_ACQUIRE_METHOD_H
+#define PKGLIB_CDROMUTL_H
#include <string>
using std::string;
-#ifdef __GNUG__
-#pragma interface "apt-pkg/cdromutl.h"
-#endif
-
bool MountCdrom(string Path);
bool UnmountCdrom(string Path);
bool IdentCdrom(string CD,string &Res,unsigned int Version = 2);
+bool IsMounted(string &Path);
#endif
diff --git a/apt-pkg/contrib/cmndline.cc b/apt-pkg/contrib/cmndline.cc
index 2b3d7dc96..54c91d67d 100644
--- a/apt-pkg/contrib/cmndline.cc
+++ b/apt-pkg/contrib/cmndline.cc
@@ -11,9 +11,6 @@
##################################################################### */
/*}}}*/
// Include files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/cmndline.h"
-#endif
#include <apt-pkg/cmndline.h>
#include <apt-pkg/error.h>
#include <apt-pkg/strutl.h>
diff --git a/apt-pkg/contrib/cmndline.h b/apt-pkg/contrib/cmndline.h
index 8f461296f..fad6d1da9 100644
--- a/apt-pkg/contrib/cmndline.h
+++ b/apt-pkg/contrib/cmndline.h
@@ -44,9 +44,7 @@
#ifndef PKGLIB_CMNDLINE_H
#define PKGLIB_CMNDLINE_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/cmndline.h"
-#endif
+
#include <apt-pkg/configuration.h>
diff --git a/apt-pkg/contrib/configuration.cc b/apt-pkg/contrib/configuration.cc
index 14a000fa5..e8301d918 100644
--- a/apt-pkg/contrib/configuration.cc
+++ b/apt-pkg/contrib/configuration.cc
@@ -15,9 +15,6 @@
##################################################################### */
/*}}}*/
// Include files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/configuration.h"
-#endif
#include <apt-pkg/configuration.h>
#include <apt-pkg/error.h>
#include <apt-pkg/strutl.h>
@@ -176,6 +173,11 @@ string Configuration::Find(const char *Name,const char *Default) const
*/
string Configuration::FindFile(const char *Name,const char *Default) const
{
+ const Item *RootItem = Lookup("RootDir");
+ std::string rootDir = (RootItem == 0) ? "" : RootItem->Value;
+ if(rootDir.size() > 0 && rootDir[rootDir.size() - 1] != '/')
+ rootDir.push_back('/');
+
const Item *Itm = Lookup(Name);
if (Itm == 0 || Itm->Value.empty() == true)
{
@@ -207,7 +209,7 @@ string Configuration::FindFile(const char *Name,const char *Default) const
Itm = Itm->Parent;
}
- return val;
+ return rootDir + val;
}
/*}}}*/
// Configuration::FindDir - Find a directory name /*{{{*/
@@ -425,6 +427,7 @@ bool Configuration::ExistsAny(const char *Name) const
string key = Name;
if (key.size() > 2 && key.end()[-2] == '/')
+ {
if (key.find_first_of("fdbi",key.size()-1) < key.size())
{
key.resize(key.size() - 2);
@@ -435,7 +438,7 @@ bool Configuration::ExistsAny(const char *Name) const
{
_error->Warning(_("Unrecognized type abbreviation: '%c'"), key.end()[-3]);
}
-
+ }
return Exists(Name);
}
/*}}}*/
@@ -509,7 +512,7 @@ bool ReadConfigFile(Configuration &Conf,const string &FName,bool AsSectional,
CurLine++;
// This should be made to work instead, but this is better than looping
if (F.fail() && !F.eof())
- return _error->Error(_("Line %d too long (max %d)"), CurLine, sizeof(Buffer));
+ return _error->Error(_("Line %d too long (max %u)"), CurLine, sizeof(Buffer));
_strtabexpand(Buffer,sizeof(Buffer));
_strstrip(Buffer);
diff --git a/apt-pkg/contrib/configuration.h b/apt-pkg/contrib/configuration.h
index 0d4078dab..2534692a3 100644
--- a/apt-pkg/contrib/configuration.h
+++ b/apt-pkg/contrib/configuration.h
@@ -28,9 +28,7 @@
#ifndef PKGLIB_CONFIGURATION_H
#define PKGLIB_CONFIGURATION_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/configuration.h"
-#endif
+
#include <string>
#include <iostream>
diff --git a/apt-pkg/contrib/crc-16.cc b/apt-pkg/contrib/crc-16.cc
index 52a551802..b300ed67e 100644
--- a/apt-pkg/contrib/crc-16.cc
+++ b/apt-pkg/contrib/crc-16.cc
@@ -15,10 +15,6 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/crc-16.h"
-#endif
-
#include <apt-pkg/crc-16.h>
/*}}}*/
diff --git a/apt-pkg/contrib/crc-16.h b/apt-pkg/contrib/crc-16.h
index 757104c54..f30678bac 100644
--- a/apt-pkg/contrib/crc-16.h
+++ b/apt-pkg/contrib/crc-16.h
@@ -10,10 +10,6 @@
#ifndef APTPKG_CRC16_H
#define APTPKG_CRC16_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/crc-16.h"
-#endif
-
#define INIT_FCS 0xffff
unsigned short AddCRC16(unsigned short fcs, void const *buf,
unsigned long len);
diff --git a/apt-pkg/contrib/error.cc b/apt-pkg/contrib/error.cc
index 5fe9bdfce..db8c53c36 100644
--- a/apt-pkg/contrib/error.cc
+++ b/apt-pkg/contrib/error.cc
@@ -14,19 +14,17 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/error.h"
-#endif
-
#include <apt-pkg/error.h>
#include <iostream>
#include <errno.h>
#include <stdio.h>
-#include <string>
#include <stdarg.h>
#include <unistd.h>
+#include <string>
+#include <cstring>
+
#include "config.h"
/*}}}*/
diff --git a/apt-pkg/contrib/error.h b/apt-pkg/contrib/error.h
index a5fc1a223..a3be6a575 100644
--- a/apt-pkg/contrib/error.h
+++ b/apt-pkg/contrib/error.h
@@ -40,9 +40,7 @@
#ifndef PKGLIB_ERROR_H
#define PKGLIB_ERROR_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/error.h"
-#endif
+
#ifdef __GNUG__
// Methods have a hidden this parameter that is visible to this attribute
diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc
index 77287952a..2b7e25080 100644
--- a/apt-pkg/contrib/fileutl.cc
+++ b/apt-pkg/contrib/fileutl.cc
@@ -17,9 +17,6 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/fileutl.h"
-#endif
#include <apt-pkg/fileutl.h>
#include <apt-pkg/error.h>
#include <apt-pkg/sptr.h>
@@ -27,6 +24,9 @@
#include <apti18n.h>
+#include <cstdlib>
+#include <cstring>
+
#include <iostream>
#include <unistd.h>
#include <fcntl.h>
diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h
index 363dd041d..73b5ea3be 100644
--- a/apt-pkg/contrib/fileutl.h
+++ b/apt-pkg/contrib/fileutl.h
@@ -21,9 +21,6 @@
#ifndef PKGLIB_FILEUTL_H
#define PKGLIB_FILEUTL_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/fileutl.h"
-#endif
#include <string>
diff --git a/apt-pkg/contrib/hashes.cc b/apt-pkg/contrib/hashes.cc
index b17b94319..fcc2f887c 100644
--- a/apt-pkg/contrib/hashes.cc
+++ b/apt-pkg/contrib/hashes.cc
@@ -11,16 +11,96 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/hashes.h"
-#endif
-
#include <apt-pkg/hashes.h>
+#include <apt-pkg/fileutl.h>
+#include <apt-pkg/configuration.h>
#include <unistd.h>
#include <system.h>
+#include <string>
+#include <iostream>
/*}}}*/
+const char* HashString::_SupportedHashes[] =
+{
+ "SHA256", "SHA1", "MD5Sum", NULL
+};
+
+HashString::HashString()
+{
+}
+
+HashString::HashString(string Type, string Hash) : Type(Type), Hash(Hash)
+{
+}
+
+HashString::HashString(string StringedHash)
+{
+ // legacy: md5sum without "MD5Sum:" prefix
+ if (StringedHash.find(":") == string::npos && StringedHash.size() == 32)
+ {
+ Type = "MD5Sum";
+ Hash = StringedHash;
+ return;
+ }
+ string::size_type pos = StringedHash.find(":");
+ Type = StringedHash.substr(0,pos);
+ Hash = StringedHash.substr(pos+1, StringedHash.size() - pos);
+
+ if(_config->FindB("Debug::Hashes",false) == true)
+ std::clog << "HashString(string): " << Type << " : " << Hash << std::endl;
+}
+
+
+bool HashString::VerifyFile(string filename) const
+{
+ FileFd fd;
+ MD5Summation MD5;
+ SHA1Summation SHA1;
+ SHA256Summation SHA256;
+ string fileHash;
+
+ FileFd Fd(filename, FileFd::ReadOnly);
+ if(Type == "MD5Sum")
+ {
+ MD5.AddFD(Fd.Fd(), Fd.Size());
+ fileHash = (string)MD5.Result();
+ }
+ else if (Type == "SHA1")
+ {
+ SHA1.AddFD(Fd.Fd(), Fd.Size());
+ fileHash = (string)SHA1.Result();
+ }
+ else if (Type == "SHA256")
+ {
+ SHA256.AddFD(Fd.Fd(), Fd.Size());
+ fileHash = (string)SHA256.Result();
+ }
+ Fd.Close();
+
+ if(_config->FindB("Debug::Hashes",false) == true)
+ std::clog << "HashString::VerifyFile: got: " << fileHash << " expected: " << toStr() << std::endl;
+
+ return (fileHash == Hash);
+}
+
+const char** HashString::SupportedHashes()
+{
+ return _SupportedHashes;
+}
+
+bool HashString::empty() const
+{
+ return (Type.empty() || Hash.empty());
+}
+
+
+string HashString::toStr() const
+{
+ return Type+string(":")+Hash;
+}
+
+
// Hashes::AddFD - Add the contents of the FD /*{{{*/
// ---------------------------------------------------------------------
/* */
@@ -36,6 +116,7 @@ bool Hashes::AddFD(int Fd,unsigned long Size)
Size -= Res;
MD5.Add(Buf,Res);
SHA1.Add(Buf,Res);
+ SHA256.Add(Buf,Res);
}
return true;
}
diff --git a/apt-pkg/contrib/hashes.h b/apt-pkg/contrib/hashes.h
index 40bbe00a0..264f7fe90 100644
--- a/apt-pkg/contrib/hashes.h
+++ b/apt-pkg/contrib/hashes.h
@@ -13,16 +13,45 @@
#ifndef APTPKG_HASHES_H
#define APTPKG_HASHES_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/hashes.h"
-#endif
#include <apt-pkg/md5.h>
#include <apt-pkg/sha1.h>
+#include <apt-pkg/sha256.h>
#include <algorithm>
+#include <vector>
+#include <cstring>
using std::min;
+using std::vector;
+
+// helper class that contains hash function name
+// and hash
+class HashString
+{
+ protected:
+ string Type;
+ string Hash;
+ static const char * _SupportedHashes[10];
+
+ public:
+ HashString(string Type, string Hash);
+ HashString(string StringedHashString); // init from str as "type:hash"
+ HashString();
+
+ // get hash type used
+ string HashType() { return Type; };
+
+ // verify the given filename against the currently loaded hash
+ bool VerifyFile(string filename) const;
+
+ // helper
+ string toStr() const; // convert to str as "type:hash"
+ bool empty() const;
+
+ // return the list of hashes we support
+ static const char** SupportedHashes();
+};
class Hashes
{
@@ -30,10 +59,11 @@ class Hashes
MD5Summation MD5;
SHA1Summation SHA1;
+ SHA256Summation SHA256;
inline bool Add(const unsigned char *Data,unsigned long Size)
{
- return MD5.Add(Data,Size) && SHA1.Add(Data,Size);
+ return MD5.Add(Data,Size) && SHA1.Add(Data,Size) && SHA256.Add(Data,Size);
};
inline bool Add(const char *Data) {return Add((unsigned char *)Data,strlen(Data));};
bool AddFD(int Fd,unsigned long Size);
diff --git a/apt-pkg/contrib/md5.cc b/apt-pkg/contrib/md5.cc
index fded5c864..a095f8f0f 100644
--- a/apt-pkg/contrib/md5.cc
+++ b/apt-pkg/contrib/md5.cc
@@ -35,10 +35,6 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/md5.h"
-#endif
-
#include <apt-pkg/md5.h>
#include <apt-pkg/strutl.h>
@@ -48,6 +44,7 @@
#include <inttypes.h>
#include <config.h>
#include <system.h>
+
/*}}}*/
// byteSwap - Swap bytes in a buffer /*{{{*/
diff --git a/apt-pkg/contrib/md5.h b/apt-pkg/contrib/md5.h
index e280d714e..96c8975b4 100644
--- a/apt-pkg/contrib/md5.h
+++ b/apt-pkg/contrib/md5.h
@@ -23,11 +23,9 @@
#ifndef APTPKG_MD5_H
#define APTPKG_MD5_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/md5.h"
-#endif
#include <string>
+#include <cstring>
#include <algorithm>
#include <stdint.h>
diff --git a/apt-pkg/contrib/mmap.cc b/apt-pkg/contrib/mmap.cc
index e395e6cc7..abcae46fe 100644
--- a/apt-pkg/contrib/mmap.cc
+++ b/apt-pkg/contrib/mmap.cc
@@ -21,10 +21,6 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/mmap.h"
-#endif
-
#define _BSD_SOURCE
#include <apt-pkg/mmap.h>
#include <apt-pkg/error.h>
@@ -35,6 +31,8 @@
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
+
+#include <cstring>
/*}}}*/
// MMap::MMap - Constructor /*{{{*/
@@ -119,7 +117,7 @@ bool MMap::Sync()
#ifdef _POSIX_SYNCHRONIZED_IO
if ((Flags & ReadOnly) != ReadOnly)
- if (msync((char *)Base,iSize,MS_SYNC) != 0)
+ if (msync((char *)Base,iSize,MS_SYNC) < 0)
return _error->Errno("msync","Unable to write mmap");
#endif
return true;
@@ -136,7 +134,7 @@ bool MMap::Sync(unsigned long Start,unsigned long Stop)
#ifdef _POSIX_SYNCHRONIZED_IO
unsigned long PSize = sysconf(_SC_PAGESIZE);
if ((Flags & ReadOnly) != ReadOnly)
- if (msync((char *)Base+(int)(Start/PSize)*PSize,Stop - Start,MS_SYNC) != 0)
+ if (msync((char *)Base+(int)(Start/PSize)*PSize,Stop - Start,MS_SYNC) < 0)
return _error->Errno("msync","Unable to write mmap");
#endif
return true;
diff --git a/apt-pkg/contrib/mmap.h b/apt-pkg/contrib/mmap.h
index e329b167a..19cf7582d 100644
--- a/apt-pkg/contrib/mmap.h
+++ b/apt-pkg/contrib/mmap.h
@@ -25,9 +25,6 @@
#ifndef PKGLIB_MMAP_H
#define PKGLIB_MMAP_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/mmap.h"
-#endif
#include <string>
#include <apt-pkg/fileutl.h>
diff --git a/apt-pkg/contrib/progress.cc b/apt-pkg/contrib/progress.cc
index cb272e389..cffdddc4f 100644
--- a/apt-pkg/contrib/progress.cc
+++ b/apt-pkg/contrib/progress.cc
@@ -8,9 +8,6 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/progress.h"
-#endif
#include <apt-pkg/progress.h>
#include <apt-pkg/error.h>
#include <apt-pkg/configuration.h>
@@ -19,6 +16,7 @@
#include <iostream>
#include <stdio.h>
+#include <cstring>
/*}}}*/
using namespace std;
@@ -115,6 +113,8 @@ bool OpProgress::CheckChange(float Interval)
if ((int)LastPercent == (int)Percent)
return false;
+
+ LastPercent = Percent;
if (Interval == 0)
return false;
@@ -126,7 +126,6 @@ bool OpProgress::CheckChange(float Interval)
if (Diff < Interval)
return false;
LastTime = Now;
- LastPercent = Percent;
return true;
}
/*}}}*/
diff --git a/apt-pkg/contrib/progress.h b/apt-pkg/contrib/progress.h
index 20caf4cdf..7dd004f7e 100644
--- a/apt-pkg/contrib/progress.h
+++ b/apt-pkg/contrib/progress.h
@@ -21,9 +21,6 @@
#ifndef PKGLIB_PROGRESS_H
#define PKGLIB_PROGRESS_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/progress.h"
-#endif
#include <string>
#include <sys/time.h>
diff --git a/apt-pkg/contrib/sha1.cc b/apt-pkg/contrib/sha1.cc
index 72eafd4ca..b70f31dc6 100644
--- a/apt-pkg/contrib/sha1.cc
+++ b/apt-pkg/contrib/sha1.cc
@@ -29,10 +29,6 @@
*/
/*}}} */
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/sha1.h"
-#endif
-
#include <apt-pkg/sha1.h>
#include <apt-pkg/strutl.h>
diff --git a/apt-pkg/contrib/sha1.h b/apt-pkg/contrib/sha1.h
index db8ca7893..8ddd889f1 100644
--- a/apt-pkg/contrib/sha1.h
+++ b/apt-pkg/contrib/sha1.h
@@ -14,11 +14,8 @@
#ifndef APTPKG_SHA1_H
#define APTPKG_SHA1_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/sha1.h"
-#endif
-
#include <string>
+#include <cstring>
#include <algorithm>
using std::string;
diff --git a/apt-pkg/contrib/sha256.cc b/apt-pkg/contrib/sha256.cc
new file mode 100644
index 000000000..ecda3d8e8
--- /dev/null
+++ b/apt-pkg/contrib/sha256.cc
@@ -0,0 +1,430 @@
+/*
+ * Cryptographic API.
+ *
+ * SHA-256, as specified in
+ * http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf
+ *
+ * SHA-256 code by Jean-Luc Cooke <jlcooke@certainkey.com>.
+ *
+ * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com>
+ * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ *
+ * Ported from the Linux kernel to Apt by Anthony Towns <ajt@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#ifdef __GNUG__
+#pragma implementation "apt-pkg/sha256.h"
+#endif
+
+
+#define SHA256_DIGEST_SIZE 32
+#define SHA256_HMAC_BLOCK_SIZE 64
+
+#define ror32(value,bits) (((value) >> (bits)) | ((value) << (32 - (bits))))
+
+#include <apt-pkg/sha256.h>
+#include <apt-pkg/strutl.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <arpa/inet.h>
+
+typedef uint32_t u32;
+typedef uint8_t u8;
+
+static inline u32 Ch(u32 x, u32 y, u32 z)
+{
+ return z ^ (x & (y ^ z));
+}
+
+static inline u32 Maj(u32 x, u32 y, u32 z)
+{
+ return (x & y) | (z & (x | y));
+}
+
+#define e0(x) (ror32(x, 2) ^ ror32(x,13) ^ ror32(x,22))
+#define e1(x) (ror32(x, 6) ^ ror32(x,11) ^ ror32(x,25))
+#define s0(x) (ror32(x, 7) ^ ror32(x,18) ^ (x >> 3))
+#define s1(x) (ror32(x,17) ^ ror32(x,19) ^ (x >> 10))
+
+#define H0 0x6a09e667
+#define H1 0xbb67ae85
+#define H2 0x3c6ef372
+#define H3 0xa54ff53a
+#define H4 0x510e527f
+#define H5 0x9b05688c
+#define H6 0x1f83d9ab
+#define H7 0x5be0cd19
+
+static inline void LOAD_OP(int I, u32 *W, const u8 *input)
+{
+ W[I] = ( ((u32) input[I * 4 + 0] << 24)
+ | ((u32) input[I * 4 + 1] << 16)
+ | ((u32) input[I * 4 + 2] << 8)
+ | ((u32) input[I * 4 + 3]));
+}
+
+static inline void BLEND_OP(int I, u32 *W)
+{
+ W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16];
+}
+
+static void sha256_transform(u32 *state, const u8 *input)
+{
+ u32 a, b, c, d, e, f, g, h, t1, t2;
+ u32 W[64];
+ int i;
+
+ /* load the input */
+ for (i = 0; i < 16; i++)
+ LOAD_OP(i, W, input);
+
+ /* now blend */
+ for (i = 16; i < 64; i++)
+ BLEND_OP(i, W);
+
+ /* load the state into our registers */
+ a=state[0]; b=state[1]; c=state[2]; d=state[3];
+ e=state[4]; f=state[5]; g=state[6]; h=state[7];
+
+ /* now iterate */
+ t1 = h + e1(e) + Ch(e,f,g) + 0x428a2f98 + W[ 0];
+ t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2;
+ t1 = g + e1(d) + Ch(d,e,f) + 0x71374491 + W[ 1];
+ t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2;
+ t1 = f + e1(c) + Ch(c,d,e) + 0xb5c0fbcf + W[ 2];
+ t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2;
+ t1 = e + e1(b) + Ch(b,c,d) + 0xe9b5dba5 + W[ 3];
+ t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2;
+ t1 = d + e1(a) + Ch(a,b,c) + 0x3956c25b + W[ 4];
+ t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2;
+ t1 = c + e1(h) + Ch(h,a,b) + 0x59f111f1 + W[ 5];
+ t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2;
+ t1 = b + e1(g) + Ch(g,h,a) + 0x923f82a4 + W[ 6];
+ t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2;
+ t1 = a + e1(f) + Ch(f,g,h) + 0xab1c5ed5 + W[ 7];
+ t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2;
+
+ t1 = h + e1(e) + Ch(e,f,g) + 0xd807aa98 + W[ 8];
+ t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2;
+ t1 = g + e1(d) + Ch(d,e,f) + 0x12835b01 + W[ 9];
+ t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2;
+ t1 = f + e1(c) + Ch(c,d,e) + 0x243185be + W[10];
+ t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2;
+ t1 = e + e1(b) + Ch(b,c,d) + 0x550c7dc3 + W[11];
+ t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2;
+ t1 = d + e1(a) + Ch(a,b,c) + 0x72be5d74 + W[12];
+ t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2;
+ t1 = c + e1(h) + Ch(h,a,b) + 0x80deb1fe + W[13];
+ t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2;
+ t1 = b + e1(g) + Ch(g,h,a) + 0x9bdc06a7 + W[14];
+ t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2;
+ t1 = a + e1(f) + Ch(f,g,h) + 0xc19bf174 + W[15];
+ t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2;
+
+ t1 = h + e1(e) + Ch(e,f,g) + 0xe49b69c1 + W[16];
+ t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2;
+ t1 = g + e1(d) + Ch(d,e,f) + 0xefbe4786 + W[17];
+ t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2;
+ t1 = f + e1(c) + Ch(c,d,e) + 0x0fc19dc6 + W[18];
+ t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2;
+ t1 = e + e1(b) + Ch(b,c,d) + 0x240ca1cc + W[19];
+ t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2;
+ t1 = d + e1(a) + Ch(a,b,c) + 0x2de92c6f + W[20];
+ t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2;
+ t1 = c + e1(h) + Ch(h,a,b) + 0x4a7484aa + W[21];
+ t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2;
+ t1 = b + e1(g) + Ch(g,h,a) + 0x5cb0a9dc + W[22];
+ t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2;
+ t1 = a + e1(f) + Ch(f,g,h) + 0x76f988da + W[23];
+ t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2;
+
+ t1 = h + e1(e) + Ch(e,f,g) + 0x983e5152 + W[24];
+ t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2;
+ t1 = g + e1(d) + Ch(d,e,f) + 0xa831c66d + W[25];
+ t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2;
+ t1 = f + e1(c) + Ch(c,d,e) + 0xb00327c8 + W[26];
+ t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2;
+ t1 = e + e1(b) + Ch(b,c,d) + 0xbf597fc7 + W[27];
+ t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2;
+ t1 = d + e1(a) + Ch(a,b,c) + 0xc6e00bf3 + W[28];
+ t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2;
+ t1 = c + e1(h) + Ch(h,a,b) + 0xd5a79147 + W[29];
+ t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2;
+ t1 = b + e1(g) + Ch(g,h,a) + 0x06ca6351 + W[30];
+ t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2;
+ t1 = a + e1(f) + Ch(f,g,h) + 0x14292967 + W[31];
+ t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2;
+
+ t1 = h + e1(e) + Ch(e,f,g) + 0x27b70a85 + W[32];
+ t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2;
+ t1 = g + e1(d) + Ch(d,e,f) + 0x2e1b2138 + W[33];
+ t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2;
+ t1 = f + e1(c) + Ch(c,d,e) + 0x4d2c6dfc + W[34];
+ t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2;
+ t1 = e + e1(b) + Ch(b,c,d) + 0x53380d13 + W[35];
+ t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2;
+ t1 = d + e1(a) + Ch(a,b,c) + 0x650a7354 + W[36];
+ t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2;
+ t1 = c + e1(h) + Ch(h,a,b) + 0x766a0abb + W[37];
+ t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2;
+ t1 = b + e1(g) + Ch(g,h,a) + 0x81c2c92e + W[38];
+ t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2;
+ t1 = a + e1(f) + Ch(f,g,h) + 0x92722c85 + W[39];
+ t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2;
+
+ t1 = h + e1(e) + Ch(e,f,g) + 0xa2bfe8a1 + W[40];
+ t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2;
+ t1 = g + e1(d) + Ch(d,e,f) + 0xa81a664b + W[41];
+ t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2;
+ t1 = f + e1(c) + Ch(c,d,e) + 0xc24b8b70 + W[42];
+ t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2;
+ t1 = e + e1(b) + Ch(b,c,d) + 0xc76c51a3 + W[43];
+ t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2;
+ t1 = d + e1(a) + Ch(a,b,c) + 0xd192e819 + W[44];
+ t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2;
+ t1 = c + e1(h) + Ch(h,a,b) + 0xd6990624 + W[45];
+ t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2;
+ t1 = b + e1(g) + Ch(g,h,a) + 0xf40e3585 + W[46];
+ t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2;
+ t1 = a + e1(f) + Ch(f,g,h) + 0x106aa070 + W[47];
+ t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2;
+
+ t1 = h + e1(e) + Ch(e,f,g) + 0x19a4c116 + W[48];
+ t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2;
+ t1 = g + e1(d) + Ch(d,e,f) + 0x1e376c08 + W[49];
+ t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2;
+ t1 = f + e1(c) + Ch(c,d,e) + 0x2748774c + W[50];
+ t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2;
+ t1 = e + e1(b) + Ch(b,c,d) + 0x34b0bcb5 + W[51];
+ t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2;
+ t1 = d + e1(a) + Ch(a,b,c) + 0x391c0cb3 + W[52];
+ t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2;
+ t1 = c + e1(h) + Ch(h,a,b) + 0x4ed8aa4a + W[53];
+ t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2;
+ t1 = b + e1(g) + Ch(g,h,a) + 0x5b9cca4f + W[54];
+ t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2;
+ t1 = a + e1(f) + Ch(f,g,h) + 0x682e6ff3 + W[55];
+ t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2;
+
+ t1 = h + e1(e) + Ch(e,f,g) + 0x748f82ee + W[56];
+ t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2;
+ t1 = g + e1(d) + Ch(d,e,f) + 0x78a5636f + W[57];
+ t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2;
+ t1 = f + e1(c) + Ch(c,d,e) + 0x84c87814 + W[58];
+ t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2;
+ t1 = e + e1(b) + Ch(b,c,d) + 0x8cc70208 + W[59];
+ t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2;
+ t1 = d + e1(a) + Ch(a,b,c) + 0x90befffa + W[60];
+ t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2;
+ t1 = c + e1(h) + Ch(h,a,b) + 0xa4506ceb + W[61];
+ t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2;
+ t1 = b + e1(g) + Ch(g,h,a) + 0xbef9a3f7 + W[62];
+ t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2;
+ t1 = a + e1(f) + Ch(f,g,h) + 0xc67178f2 + W[63];
+ t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2;
+
+ state[0] += a; state[1] += b; state[2] += c; state[3] += d;
+ state[4] += e; state[5] += f; state[6] += g; state[7] += h;
+
+ /* clear any sensitive info... */
+ a = b = c = d = e = f = g = h = t1 = t2 = 0;
+ memset(W, 0, 64 * sizeof(u32));
+}
+
+SHA256Summation::SHA256Summation()
+{
+ Sum.state[0] = H0;
+ Sum.state[1] = H1;
+ Sum.state[2] = H2;
+ Sum.state[3] = H3;
+ Sum.state[4] = H4;
+ Sum.state[5] = H5;
+ Sum.state[6] = H6;
+ Sum.state[7] = H7;
+ Sum.count[0] = Sum.count[1] = 0;
+ memset(Sum.buf, 0, sizeof(Sum.buf));
+ Done = false;
+}
+
+bool SHA256Summation::Add(const u8 *data, unsigned long len)
+{
+ struct sha256_ctx *sctx = &Sum;
+ unsigned int i, index, part_len;
+
+ if (Done) return false;
+
+ /* Compute number of bytes mod 128 */
+ index = (unsigned int)((sctx->count[0] >> 3) & 0x3f);
+
+ /* Update number of bits */
+ if ((sctx->count[0] += (len << 3)) < (len << 3)) {
+ sctx->count[1]++;
+ sctx->count[1] += (len >> 29);
+ }
+
+ part_len = 64 - index;
+
+ /* Transform as many times as possible. */
+ if (len >= part_len) {
+ memcpy(&sctx->buf[index], data, part_len);
+ sha256_transform(sctx->state, sctx->buf);
+
+ for (i = part_len; i + 63 < len; i += 64)
+ sha256_transform(sctx->state, &data[i]);
+ index = 0;
+ } else {
+ i = 0;
+ }
+
+ /* Buffer remaining input */
+ memcpy(&sctx->buf[index], &data[i], len-i);
+
+ return true;
+}
+
+SHA256SumValue SHA256Summation::Result()
+{
+ struct sha256_ctx *sctx = &Sum;
+ if (!Done) {
+ u8 bits[8];
+ unsigned int index, pad_len, t;
+ static const u8 padding[64] = { 0x80, };
+
+ /* Save number of bits */
+ t = sctx->count[0];
+ bits[7] = t; t >>= 8;
+ bits[6] = t; t >>= 8;
+ bits[5] = t; t >>= 8;
+ bits[4] = t;
+ t = sctx->count[1];
+ bits[3] = t; t >>= 8;
+ bits[2] = t; t >>= 8;
+ bits[1] = t; t >>= 8;
+ bits[0] = t;
+
+ /* Pad out to 56 mod 64. */
+ index = (sctx->count[0] >> 3) & 0x3f;
+ pad_len = (index < 56) ? (56 - index) : ((64+56) - index);
+ Add(padding, pad_len);
+
+ /* Append length (before padding) */
+ Add(bits, 8);
+ }
+
+ Done = true;
+
+ /* Store state in digest */
+
+ SHA256SumValue res;
+ u8 *out = res.Sum;
+
+ int i, j;
+ unsigned int t;
+ for (i = j = 0; i < 8; i++, j += 4) {
+ t = sctx->state[i];
+ out[j+3] = t; t >>= 8;
+ out[j+2] = t; t >>= 8;
+ out[j+1] = t; t >>= 8;
+ out[j ] = t;
+ }
+
+ return res;
+}
+
+// SHA256SumValue::SHA256SumValue - Constructs the sum from a string /*{{{*/
+// ---------------------------------------------------------------------
+/* The string form of a SHA256 is a 64 character hex number */
+SHA256SumValue::SHA256SumValue(string Str)
+{
+ memset(Sum,0,sizeof(Sum));
+ Set(Str);
+}
+
+ /*}}}*/
+// SHA256SumValue::SHA256SumValue - Default constructor /*{{{*/
+// ---------------------------------------------------------------------
+/* Sets the value to 0 */
+SHA256SumValue::SHA256SumValue()
+{
+ memset(Sum,0,sizeof(Sum));
+}
+
+ /*}}}*/
+// SHA256SumValue::Set - Set the sum from a string /*{{{*/
+// ---------------------------------------------------------------------
+/* Converts the hex string into a set of chars */
+bool SHA256SumValue::Set(string Str)
+{
+ return Hex2Num(Str,Sum,sizeof(Sum));
+}
+ /*}}}*/
+// SHA256SumValue::Value - Convert the number into a string /*{{{*/
+// ---------------------------------------------------------------------
+/* Converts the set of chars into a hex string in lower case */
+string SHA256SumValue::Value() const
+{
+ char Conv[16] =
+ { '0','1','2','3','4','5','6','7','8','9','a','b',
+ 'c','d','e','f'
+ };
+ char Result[65];
+ Result[64] = 0;
+
+ // Convert each char into two letters
+ int J = 0;
+ int I = 0;
+ for (; I != 64; J++,I += 2)
+ {
+ Result[I] = Conv[Sum[J] >> 4];
+ Result[I + 1] = Conv[Sum[J] & 0xF];
+ }
+
+ return string(Result);
+}
+
+
+
+// SHA256SumValue::operator == - Comparator /*{{{*/
+// ---------------------------------------------------------------------
+/* Call memcmp on the buffer */
+bool SHA256SumValue::operator == (const SHA256SumValue & rhs) const
+{
+ return memcmp(Sum,rhs.Sum,sizeof(Sum)) == 0;
+}
+ /*}}}*/
+
+
+// SHA256Summation::AddFD - Add content of file into the checksum /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool SHA256Summation::AddFD(int Fd,unsigned long Size)
+{
+ unsigned char Buf[64 * 64];
+ int Res = 0;
+ int ToEOF = (Size == 0);
+ while (Size != 0 || ToEOF)
+ {
+ unsigned n = sizeof(Buf);
+ if (!ToEOF) n = min(Size,(unsigned long)n);
+ Res = read(Fd,Buf,n);
+ if (Res < 0 || (!ToEOF && (unsigned) Res != n)) // error, or short read
+ return false;
+ if (ToEOF && Res == 0) // EOF
+ break;
+ Size -= Res;
+ Add(Buf,Res);
+ }
+ return true;
+}
+ /*}}}*/
+
diff --git a/apt-pkg/contrib/sha256.h b/apt-pkg/contrib/sha256.h
new file mode 100644
index 000000000..1951f053b
--- /dev/null
+++ b/apt-pkg/contrib/sha256.h
@@ -0,0 +1,71 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: sha1.h,v 1.3 2001/05/07 05:05:47 jgg Exp $
+/* ######################################################################
+
+ SHA256SumValue - Storage for a SHA-256 hash.
+ SHA256Summation - SHA-256 Secure Hash Algorithm.
+
+ This is a C++ interface to a set of SHA256Sum functions, that mirrors
+ the equivalent MD5 & SHA1 classes.
+
+ ##################################################################### */
+ /*}}}*/
+#ifndef APTPKG_SHA256_H
+#define APTPKG_SHA256_H
+
+#include <string>
+#include <cstring>
+#include <algorithm>
+
+using std::string;
+using std::min;
+
+class SHA256Summation;
+
+class SHA256SumValue
+{
+ friend class SHA256Summation;
+ unsigned char Sum[32];
+
+ public:
+
+ // Accessors
+ bool operator ==(const SHA256SumValue &rhs) const;
+ string Value() const;
+ inline void Value(unsigned char S[32])
+ {for (int I = 0; I != sizeof(Sum); I++) S[I] = Sum[I];};
+ inline operator string() const {return Value();};
+ bool Set(string Str);
+ inline void Set(unsigned char S[32])
+ {for (int I = 0; I != sizeof(Sum); I++) Sum[I] = S[I];};
+
+ SHA256SumValue(string Str);
+ SHA256SumValue();
+};
+
+struct sha256_ctx {
+ uint32_t count[2];
+ uint32_t state[8];
+ uint8_t buf[128];
+};
+
+class SHA256Summation
+{
+ struct sha256_ctx Sum;
+
+ bool Done;
+
+ public:
+
+ bool Add(const unsigned char *inbuf,unsigned long inlen);
+ inline bool Add(const char *Data) {return Add((unsigned char *)Data,strlen(Data));};
+ bool AddFD(int Fd,unsigned long Size);
+ inline bool Add(const unsigned char *Beg,const unsigned char *End)
+ {return Add(Beg,End-Beg);};
+ SHA256SumValue Result();
+
+ SHA256Summation();
+};
+
+#endif
diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc
index d96155917..a04c266ba 100644
--- a/apt-pkg/contrib/strutl.cc
+++ b/apt-pkg/contrib/strutl.cc
@@ -15,10 +15,6 @@
##################################################################### */
/*}}}*/
// Includes /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/strutl.h"
-#endif
-
#include <apt-pkg/strutl.h>
#include <apt-pkg/fileutl.h>
#include <apt-pkg/error.h>
@@ -28,16 +24,60 @@
#include <ctype.h>
#include <string.h>
#include <stdio.h>
+#include <algorithm>
#include <unistd.h>
#include <regex.h>
#include <errno.h>
#include <stdarg.h>
+#include <iconv.h>
#include "config.h"
using namespace std;
/*}}}*/
+// UTF8ToCodeset - Convert some UTF-8 string for some codeset /*{{{*/
+// ---------------------------------------------------------------------
+/* This is handy to use before display some information for enduser */
+bool UTF8ToCodeset(const char *codeset, const string &orig, string *dest)
+{
+ iconv_t cd;
+ const char *inbuf;
+ char *inptr, *outbuf, *outptr;
+ size_t insize, outsize;
+
+ cd = iconv_open(codeset, "UTF-8");
+ if (cd == (iconv_t)(-1)) {
+ // Something went wrong
+ if (errno == EINVAL)
+ _error->Error("conversion from 'UTF-8' to '%s' not available",
+ codeset);
+ else
+ perror("iconv_open");
+
+ // Clean the destination string
+ *dest = "";
+
+ return false;
+ }
+
+ insize = outsize = orig.size();
+ inbuf = orig.data();
+ inptr = (char *)inbuf;
+ outbuf = new char[insize+1];
+ outptr = outbuf;
+
+ iconv(cd, &inptr, &insize, &outptr, &outsize);
+ *outptr = '\0';
+
+ *dest = outbuf;
+ delete[] outbuf;
+
+ iconv_close(cd);
+
+ return true;
+}
+ /*}}}*/
// strstrip - Remove white space from the front and back of a string /*{{{*/
// ---------------------------------------------------------------------
/* This is handy to use when parsing a file. It also removes \n's left
@@ -291,19 +331,19 @@ string TimeToStr(unsigned long Sec)
{
if (Sec > 60*60*24)
{
- sprintf(S,"%lid %lih%lim%lis",Sec/60/60/24,(Sec/60/60) % 24,(Sec/60) % 60,Sec % 60);
+ sprintf(S,"%lid %lih%limin%lis",Sec/60/60/24,(Sec/60/60) % 24,(Sec/60) % 60,Sec % 60);
break;
}
if (Sec > 60*60)
{
- sprintf(S,"%lih%lim%lis",Sec/60/60,(Sec/60) % 60,Sec % 60);
+ sprintf(S,"%lih%limin%lis",Sec/60/60,(Sec/60) % 60,Sec % 60);
break;
}
if (Sec > 60)
{
- sprintf(S,"%lim%lis",Sec/60,Sec % 60);
+ sprintf(S,"%limin%lis",Sec/60,Sec % 60);
break;
}
diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h
index 6ec2b7811..53146ced7 100644
--- a/apt-pkg/contrib/strutl.h
+++ b/apt-pkg/contrib/strutl.h
@@ -16,12 +16,11 @@
#ifndef STRUTL_H
#define STRUTL_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/strutl.h"
-#endif
+
#include <stdlib.h>
#include <string>
+#include <cstring>
#include <vector>
#include <iostream>
#include <time.h>
@@ -38,7 +37,8 @@ using std::ostream;
#define APT_FORMAT2
#define APT_FORMAT3
#endif
-
+
+bool UTF8ToCodeset(const char *codeset, const string &orig, string *dest);
char *_strstrip(char *String);
char *_strtabexpand(char *String,size_t Len);
bool ParseQuoteWord(const char *&String,string &Res);
diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc
index ff8bce85d..ed7633803 100644
--- a/apt-pkg/deb/debindexfile.cc
+++ b/apt-pkg/deb/debindexfile.cc
@@ -9,10 +9,6 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/debindexfile.h"
-#endif
-
#include <apt-pkg/debindexfile.h>
#include <apt-pkg/debsrcrecords.h>
#include <apt-pkg/deblistparser.h>
@@ -305,7 +301,7 @@ pkgCache::PkgFileIterator debPackagesIndex::FindInCache(pkgCache &Cache) const
pkgCache::PkgFileIterator File = Cache.FileBegin();
for (; File.end() == false; File++)
{
- if (FileName != File.FileName())
+ if (File.FileName() == NULL || FileName != File.FileName())
continue;
struct stat St;
@@ -320,6 +316,170 @@ pkgCache::PkgFileIterator debPackagesIndex::FindInCache(pkgCache &Cache) const
}
/*}}}*/
+// TranslationsIndex::debTranslationsIndex - Contructor /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+debTranslationsIndex::debTranslationsIndex(string URI,string Dist,string Section) :
+ pkgIndexFile(true), URI(URI), Dist(Dist), Section(Section)
+{
+}
+ /*}}}*/
+// TranslationIndex::Trans* - Return the URI to the translation files /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+inline string debTranslationsIndex::IndexFile(const char *Type) const
+{
+ return _config->FindDir("Dir::State::lists") + URItoFileName(IndexURI(Type));
+}
+string debTranslationsIndex::IndexURI(const char *Type) const
+{
+ string Res;
+ if (Dist[Dist.size() - 1] == '/')
+ {
+ if (Dist != "/")
+ Res = URI + Dist;
+ else
+ Res = URI;
+ }
+ else
+ Res = URI + "dists/" + Dist + '/' + Section +
+ "/i18n/Translation-";
+
+ Res += Type;
+ return Res;
+}
+ /*}}}*/
+// TranslationsIndex::GetIndexes - Fetch the index files /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool debTranslationsIndex::GetIndexes(pkgAcquire *Owner) const
+{
+ if (TranslationsAvailable()) {
+ string TranslationFile = "Translation-" + LanguageCode();
+ new pkgAcqIndexTrans(Owner, IndexURI(LanguageCode().c_str()),
+ Info(TranslationFile.c_str()),
+ TranslationFile);
+ }
+
+ return true;
+}
+ /*}}}*/
+// TranslationsIndex::Describe - Give a descriptive path to the index /*{{{*/
+// ---------------------------------------------------------------------
+/* This should help the user find the index in the sources.list and
+ in the filesystem for problem solving */
+string debTranslationsIndex::Describe(bool Short) const
+{
+ char S[300];
+ if (Short == true)
+ snprintf(S,sizeof(S),"%s",Info(TranslationFile().c_str()).c_str());
+ else
+ snprintf(S,sizeof(S),"%s (%s)",Info(TranslationFile().c_str()).c_str(),
+ IndexFile(LanguageCode().c_str()).c_str());
+ return S;
+}
+ /*}}}*/
+// TranslationsIndex::Info - One liner describing the index URI /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+string debTranslationsIndex::Info(const char *Type) const
+{
+ string Info = ::URI::SiteOnly(URI) + ' ';
+ if (Dist[Dist.size() - 1] == '/')
+ {
+ if (Dist != "/")
+ Info += Dist;
+ }
+ else
+ Info += Dist + '/' + Section;
+ Info += " ";
+ Info += Type;
+ return Info;
+}
+ /*}}}*/
+bool debTranslationsIndex::HasPackages() const
+{
+ if(!TranslationsAvailable())
+ return false;
+
+ return FileExists(IndexFile(LanguageCode().c_str()));
+}
+
+// TranslationsIndex::Exists - Check if the index is available /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool debTranslationsIndex::Exists() const
+{
+ return FileExists(IndexFile(LanguageCode().c_str()));
+}
+ /*}}}*/
+// TranslationsIndex::Size - Return the size of the index /*{{{*/
+// ---------------------------------------------------------------------
+/* This is really only used for progress reporting. */
+unsigned long debTranslationsIndex::Size() const
+{
+ struct stat S;
+ if (stat(IndexFile(LanguageCode().c_str()).c_str(),&S) != 0)
+ return 0;
+ return S.st_size;
+}
+ /*}}}*/
+// TranslationsIndex::Merge - Load the index file into a cache /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const
+{
+ // Check the translation file, if in use
+ string TranslationFile = IndexFile(LanguageCode().c_str());
+ if (TranslationsAvailable() && FileExists(TranslationFile))
+ {
+ FileFd Trans(TranslationFile,FileFd::ReadOnly);
+ debListParser TransParser(&Trans);
+ if (_error->PendingError() == true)
+ return false;
+
+ Prog.SubProgress(0, Info(TranslationFile.c_str()));
+ if (Gen.SelectFile(TranslationFile,string(),*this) == false)
+ return _error->Error("Problem with SelectFile %s",TranslationFile.c_str());
+
+ // Store the IMS information
+ pkgCache::PkgFileIterator TransFile = Gen.GetCurFile();
+ struct stat TransSt;
+ if (fstat(Trans.Fd(),&TransSt) != 0)
+ return _error->Errno("fstat","Failed to stat");
+ TransFile->Size = TransSt.st_size;
+ TransFile->mtime = TransSt.st_mtime;
+
+ if (Gen.MergeList(TransParser) == false)
+ return _error->Error("Problem with MergeList %s",TranslationFile.c_str());
+ }
+
+ return true;
+}
+ /*}}}*/
+// TranslationsIndex::FindInCache - Find this index /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+pkgCache::PkgFileIterator debTranslationsIndex::FindInCache(pkgCache &Cache) const
+{
+ string FileName = IndexFile(LanguageCode().c_str());
+
+ pkgCache::PkgFileIterator File = Cache.FileBegin();
+ for (; File.end() == false; File++)
+ {
+ if (FileName != File.FileName())
+ continue;
+
+ struct stat St;
+ if (stat(File.FileName(),&St) != 0)
+ return pkgCache::PkgFileIterator(Cache);
+ if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
+ return pkgCache::PkgFileIterator(Cache);
+ return File;
+ }
+ return File;
+}
+ /*}}}*/
// StatusIndex::debStatusIndex - Constructor /*{{{*/
// ---------------------------------------------------------------------
/* */
@@ -416,6 +576,11 @@ class debIFTypePkg : public pkgIndexFile::Type
};
debIFTypePkg() {Label = "Debian Package Index";};
};
+class debIFTypeTrans : public debIFTypePkg
+{
+ public:
+ debIFTypeTrans() {Label = "Debian Translation Index";};
+};
class debIFTypeStatus : public pkgIndexFile::Type
{
public:
@@ -428,6 +593,7 @@ class debIFTypeStatus : public pkgIndexFile::Type
};
static debIFTypeSrc _apt_Src;
static debIFTypePkg _apt_Pkg;
+static debIFTypeTrans _apt_Trans;
static debIFTypeStatus _apt_Status;
const pkgIndexFile::Type *debSourcesIndex::GetType() const
@@ -438,6 +604,10 @@ const pkgIndexFile::Type *debPackagesIndex::GetType() const
{
return &_apt_Pkg;
}
+const pkgIndexFile::Type *debTranslationsIndex::GetType() const
+{
+ return &_apt_Trans;
+}
const pkgIndexFile::Type *debStatusIndex::GetType() const
{
return &_apt_Status;
diff --git a/apt-pkg/deb/debindexfile.h b/apt-pkg/deb/debindexfile.h
index a1b9583a4..b0012c96b 100644
--- a/apt-pkg/deb/debindexfile.h
+++ b/apt-pkg/deb/debindexfile.h
@@ -16,9 +16,7 @@
#ifndef PKGLIB_DEBINDEXFILE_H
#define PKGLIB_DEBINDEXFILE_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/debindexfile.h"
-#endif
+
#include <apt-pkg/indexfile.h>
@@ -74,6 +72,36 @@ class debPackagesIndex : public pkgIndexFile
debPackagesIndex(string URI,string Dist,string Section,bool Trusted);
};
+class debTranslationsIndex : public pkgIndexFile
+{
+ string URI;
+ string Dist;
+ string Section;
+
+ string Info(const char *Type) const;
+ string IndexFile(const char *Type) const;
+ string IndexURI(const char *Type) const;
+
+ inline string TranslationFile() const {return "Translation-" + LanguageCode();};
+
+ public:
+
+ virtual const Type *GetType() const;
+
+ // Interface for acquire
+ virtual string Describe(bool Short) const;
+ virtual bool GetIndexes(pkgAcquire *Owner) const;
+
+ // Interface for the Cache Generator
+ virtual bool Exists() const;
+ virtual bool HasPackages() const;
+ virtual unsigned long Size() const;
+ virtual bool Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const;
+ virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const;
+
+ debTranslationsIndex(string URI,string Dist,string Section);
+};
+
class debSourcesIndex : public pkgIndexFile
{
string URI;
diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc
index d0dc7a260..896d4d6d8 100644
--- a/apt-pkg/deb/deblistparser.cc
+++ b/apt-pkg/deb/deblistparser.cc
@@ -15,6 +15,7 @@
#include <apt-pkg/configuration.h>
#include <apt-pkg/strutl.h>
#include <apt-pkg/crc-16.h>
+#include <apt-pkg/md5.h>
#include <ctype.h>
@@ -104,6 +105,8 @@ bool debListParser::NewVersion(pkgCache::VerIterator Ver)
return false;
if (ParseDepends(Ver,"Conflicts",pkgCache::Dep::Conflicts) == false)
return false;
+ if (ParseDepends(Ver,"Breaks",pkgCache::Dep::DpkgBreaks) == false)
+ return false;
if (ParseDepends(Ver,"Replaces",pkgCache::Dep::Replaces) == false)
return false;
@@ -117,6 +120,48 @@ bool debListParser::NewVersion(pkgCache::VerIterator Ver)
return true;
}
/*}}}*/
+// ListParser::Description - Return the description string /*{{{*/
+// ---------------------------------------------------------------------
+/* This is to return the string describing the package in debian
+ form. If this returns the blank string then the entry is assumed to
+ only describe package properties */
+string debListParser::Description()
+{
+ if (DescriptionLanguage().empty())
+ return Section.FindS("Description");
+ else
+ return Section.FindS(("Description-" + pkgIndexFile::LanguageCode()).c_str());
+}
+ /*}}}*/
+// ListParser::DescriptionLanguage - Return the description lang string /*{{{*/
+// ---------------------------------------------------------------------
+/* This is to return the string describing the language of
+ description. If this returns the blank string then the entry is
+ assumed to describe original description. */
+string debListParser::DescriptionLanguage()
+{
+ return Section.FindS("Description").empty() ? pkgIndexFile::LanguageCode() : "";
+}
+ /*}}}*/
+// ListParser::Description - Return the description_md5 MD5SumValue /*{{{*/
+// ---------------------------------------------------------------------
+/* This is to return the md5 string to allow the check if it is the right
+ description. If no Description-md5 is found in the section it will be
+ calculated.
+ */
+MD5SumValue debListParser::Description_md5()
+{
+ string value = Section.FindS("Description-md5");
+
+ if (value.empty())
+ {
+ MD5Summation md5;
+ md5.Add((Description() + "\n").c_str());
+ return md5.Result();
+ } else
+ return MD5SumValue(value);
+}
+ /*}}}*/
// ListParser::UsePackage - Update a package structure /*{{{*/
// ---------------------------------------------------------------------
/* This is called to update the package with any new information
@@ -150,6 +195,7 @@ unsigned short debListParser::VersionHash()
// "Suggests",
// "Recommends",
"Conflicts",
+ "Breaks",
"Replaces",0};
unsigned long Result = INIT_FCS;
char S[1024];
@@ -247,6 +293,8 @@ bool debListParser::ParseStatus(pkgCache::PkgIterator Pkg,
{"installed",pkgCache::State::Installed},
{"half-installed",pkgCache::State::HalfInstalled},
{"config-files",pkgCache::State::ConfigFiles},
+ {"triggers-awaited",pkgCache::State::TriggersAwaited},
+ {"triggers-pending",pkgCache::State::TriggersPending},
{"post-inst-failed",pkgCache::State::HalfConfigured},
{"removal-failed",pkgCache::State::HalfInstalled},
{}};
diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h
index 3a0e0421b..34bb29c72 100644
--- a/apt-pkg/deb/deblistparser.h
+++ b/apt-pkg/deb/deblistparser.h
@@ -12,6 +12,7 @@
#define PKGLIB_DEBLISTPARSER_H
#include <apt-pkg/pkgcachegen.h>
+#include <apt-pkg/indexfile.h>
#include <apt-pkg/tagfile.h>
class debListParser : public pkgCacheGenerator::ListParser
@@ -47,6 +48,9 @@ class debListParser : public pkgCacheGenerator::ListParser
virtual string Package();
virtual string Version();
virtual bool NewVersion(pkgCache::VerIterator Ver);
+ virtual string Description();
+ virtual string DescriptionLanguage();
+ virtual MD5SumValue Description_md5();
virtual unsigned short VersionHash();
virtual bool UsePackage(pkgCache::PkgIterator Pkg,
pkgCache::VerIterator Ver);
diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc
index 85e5b16b3..9ac659f78 100644
--- a/apt-pkg/deb/debmetaindex.cc
+++ b/apt-pkg/deb/debmetaindex.cc
@@ -1,9 +1,5 @@
// ijones, walters
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/debmetaindex.h"
-#endif
-
#include <apt-pkg/debmetaindex.h>
#include <apt-pkg/debindexfile.h>
#include <apt-pkg/strutl.h>
@@ -148,7 +144,7 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool GetAll) const
vector <struct IndexTarget *> *targets = ComputeIndexTargets();
for (vector <struct IndexTarget*>::const_iterator Target = targets->begin(); Target != targets->end(); Target++) {
new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description,
- (*Target)->ShortDesc, "");
+ (*Target)->ShortDesc, HashString());
}
}
new pkgAcqMetaSig(Owner, MetaIndexURI("Release.gpg"),
@@ -157,6 +153,16 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool GetAll) const
ComputeIndexTargets(),
new indexRecords (Dist));
+ // Queue the translations
+ for (vector<const debSectionEntry *>::const_iterator I = SectionEntries.begin();
+ I != SectionEntries.end(); I++) {
+
+ if((*I)->IsSrc)
+ continue;
+ debTranslationsIndex i = debTranslationsIndex(URI,Dist,(*I)->Section);
+ i.GetIndexes(Owner);
+ }
+
return true;
}
@@ -181,11 +187,16 @@ vector <pkgIndexFile *> *debReleaseIndex::GetIndexFiles()
Indexes = new vector <pkgIndexFile*>;
for (vector<const debSectionEntry *>::const_iterator I = SectionEntries.begin();
- I != SectionEntries.end(); I++)
+ I != SectionEntries.end(); I++) {
if ((*I)->IsSrc)
Indexes->push_back(new debSourcesIndex (URI, Dist, (*I)->Section, IsTrusted()));
else
+ {
Indexes->push_back(new debPackagesIndex (URI, Dist, (*I)->Section, IsTrusted()));
+ Indexes->push_back(new debTranslationsIndex(URI, Dist, (*I)->Section));
+ }
+ }
+
return Indexes;
}
@@ -213,7 +224,7 @@ class debSLTypeDebian : public pkgSourceList::Type
// This check insures that there will be only one Release file
// queued for all the Packages files and Sources files it
// corresponds to.
- if ((*I)->GetType() == "deb")
+ if (strcmp((*I)->GetType(), "deb") == 0)
{
debReleaseIndex *Deb = (debReleaseIndex *) (*I);
// This check insures that there will be only one Release file
diff --git a/apt-pkg/deb/debmetaindex.h b/apt-pkg/deb/debmetaindex.h
index 2b9922987..c021a1b5a 100644
--- a/apt-pkg/deb/debmetaindex.h
+++ b/apt-pkg/deb/debmetaindex.h
@@ -2,10 +2,6 @@
#ifndef PKGLIB_DEBMETAINDEX_H
#define PKGLIB_DEBMETAINDEX_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/debmetaindex.h"
-#endif
-
#include <apt-pkg/metaindex.h>
#include <apt-pkg/sourcelist.h>
diff --git a/apt-pkg/deb/debrecords.cc b/apt-pkg/deb/debrecords.cc
index 6652a6ad9..8ed0bb7eb 100644
--- a/apt-pkg/deb/debrecords.cc
+++ b/apt-pkg/deb/debrecords.cc
@@ -8,11 +8,10 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/debrecords.h"
-#endif
#include <apt-pkg/debrecords.h>
+#include <apt-pkg/strutl.h>
#include <apt-pkg/error.h>
+#include <langinfo.h>
/*}}}*/
// RecordParser::debRecordParser - Constructor /*{{{*/
@@ -31,6 +30,10 @@ bool debRecordParser::Jump(pkgCache::VerFileIterator const &Ver)
{
return Tags.Jump(Section,Ver->Offset);
}
+bool debRecordParser::Jump(pkgCache::DescFileIterator const &Desc)
+{
+ return Tags.Jump(Section,Desc->Offset);
+}
/*}}}*/
// RecordParser::FileName - Return the archive filename on the site /*{{{*/
// ---------------------------------------------------------------------
@@ -48,6 +51,14 @@ string debRecordParser::Name()
return Section.FindS("Package");
}
/*}}}*/
+// RecordParser::Homepage - Return the package homepage /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+string debRecordParser::Homepage()
+{
+ return Section.FindS("Homepage");
+}
+ /*}}}*/
// RecordParser::MD5Hash - Return the archive hash /*{{{*/
// ---------------------------------------------------------------------
/* */
@@ -61,7 +72,15 @@ string debRecordParser::MD5Hash()
/* */
string debRecordParser::SHA1Hash()
{
- return Section.FindS("SHA1Sum");
+ return Section.FindS("SHA1");
+}
+ /*}}}*/
+// RecordParser::SHA1Hash - Return the archive hash /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+string debRecordParser::SHA256Hash()
+{
+ return Section.FindS("SHA256");
}
/*}}}*/
// RecordParser::Maintainer - Return the maintainer email /*{{{*/
@@ -77,7 +96,7 @@ string debRecordParser::Maintainer()
/* */
string debRecordParser::ShortDesc()
{
- string Res = Section.FindS("Description");
+ string Res = LongDesc();
string::size_type Pos = Res.find('\n');
if (Pos == string::npos)
return Res;
@@ -89,21 +108,60 @@ string debRecordParser::ShortDesc()
/* */
string debRecordParser::LongDesc()
{
- return Section.FindS("Description");
+ string orig, dest;
+ char *codeset = nl_langinfo(CODESET);
+
+ if (!Section.FindS("Description").empty())
+ orig = Section.FindS("Description").c_str();
+ else
+ orig = Section.FindS(("Description-" + pkgIndexFile::LanguageCode()).c_str()).c_str();
+
+ if (strcmp(codeset,"UTF-8") != 0) {
+ UTF8ToCodeset(codeset, orig, &dest);
+ orig = dest;
+ }
+
+ return orig;
}
/*}}}*/
+
+static const char *SourceVerSeparators = " ()";
+
// RecordParser::SourcePkg - Return the source package name if any /*{{{*/
// ---------------------------------------------------------------------
/* */
string debRecordParser::SourcePkg()
{
string Res = Section.FindS("Source");
- string::size_type Pos = Res.find(' ');
+ string::size_type Pos = Res.find_first_of(SourceVerSeparators);
if (Pos == string::npos)
return Res;
return string(Res,0,Pos);
}
/*}}}*/
+// RecordParser::SourceVer - Return the source version number if present /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+string debRecordParser::SourceVer()
+{
+ string Pkg = Section.FindS("Source");
+ string::size_type Pos = Pkg.find_first_of(SourceVerSeparators);
+ if (Pos == string::npos)
+ return "";
+
+ string::size_type VerStart = Pkg.find_first_not_of(SourceVerSeparators, Pos);
+ if(VerStart == string::npos)
+ return "";
+
+ string::size_type VerEnd = Pkg.find_first_of(SourceVerSeparators, VerStart);
+ if(VerEnd == string::npos)
+ // Corresponds to the case of, e.g., "foo (1.2" without a closing
+ // paren. Be liberal and guess what it means.
+ return string(Pkg, VerStart);
+ else
+ return string(Pkg, VerStart, VerEnd - VerStart);
+}
+ /*}}}*/
// RecordParser::GetRec - Return the whole record /*{{{*/
// ---------------------------------------------------------------------
/* */
diff --git a/apt-pkg/deb/debrecords.h b/apt-pkg/deb/debrecords.h
index efef2e588..6f358abfa 100644
--- a/apt-pkg/deb/debrecords.h
+++ b/apt-pkg/deb/debrecords.h
@@ -14,11 +14,8 @@
#ifndef PKGLIB_DEBRECORDS_H
#define PKGLIB_DEBRECORDS_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/debrecords.h"
-#endif
-
#include <apt-pkg/pkgrecords.h>
+#include <apt-pkg/indexfile.h>
#include <apt-pkg/tagfile.h>
class debRecordParser : public pkgRecords::Parser
@@ -30,6 +27,7 @@ class debRecordParser : public pkgRecords::Parser
protected:
virtual bool Jump(pkgCache::VerFileIterator const &Ver);
+ virtual bool Jump(pkgCache::DescFileIterator const &Desc);
public:
@@ -37,13 +35,16 @@ class debRecordParser : public pkgRecords::Parser
virtual string FileName();
virtual string MD5Hash();
virtual string SHA1Hash();
+ virtual string SHA256Hash();
virtual string SourcePkg();
+ virtual string SourceVer();
// These are some general stats about the package
virtual string Maintainer();
virtual string ShortDesc();
virtual string LongDesc();
virtual string Name();
+ virtual string Homepage();
virtual void GetRec(const char *&Start,const char *&Stop);
diff --git a/apt-pkg/deb/debsrcrecords.cc b/apt-pkg/deb/debsrcrecords.cc
index cac36c2e6..ace4e00b5 100644
--- a/apt-pkg/deb/debsrcrecords.cc
+++ b/apt-pkg/deb/debsrcrecords.cc
@@ -9,15 +9,13 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/debsrcrecords.h"
-#endif
-
#include <apt-pkg/deblistparser.h>
#include <apt-pkg/debsrcrecords.h>
#include <apt-pkg/error.h>
#include <apt-pkg/strutl.h>
#include <apt-pkg/configuration.h>
+
+using std::max;
/*}}}*/
// SrcRecordParser::Binaries - Return the binaries field /*{{{*/
@@ -34,31 +32,19 @@ const char **debSrcRecordParser::Binaries()
if (Bins.empty() == true || Bins.length() >= 102400)
return 0;
- // Workaround for #236688. Only allocate a new buffer if the field
- // is large, to avoid a performance penalty
- char *BigBuf = NULL;
- char *Buf;
- if (Bins.length() > sizeof(Buffer))
- {
- BigBuf = new char[Bins.length()];
- Buf = BigBuf;
- }
- else
+ if (Bins.length() >= BufSize)
{
- Buf = Buffer;
+ delete [] Buffer;
+ // allocate new size based on buffer (but never smaller than 4000)
+ BufSize = max((unsigned int)4000, max((unsigned int)Bins.length()+1,2*BufSize));
+ Buffer = new char[BufSize];
}
- strcpy(Buf,Bins.c_str());
- if (TokSplitString(',',Buf,StaticBinList,
+ strcpy(Buffer,Bins.c_str());
+ if (TokSplitString(',',Buffer,StaticBinList,
sizeof(StaticBinList)/sizeof(StaticBinList[0])) == false)
- {
- if (BigBuf != NULL)
- delete BigBuf;
return 0;
- }
- if (BigBuf != NULL)
- delete BigBuf;
return (const char **)StaticBinList;
}
/*}}}*/
@@ -151,7 +137,7 @@ bool debSrcRecordParser::Files(vector<pkgSrcRecords::File> &List)
break;
F.Type = string(F.Path,Tmp+1,Pos-Tmp);
- if (F.Type == "gz" || F.Type == "bz2")
+ if (F.Type == "gz" || F.Type == "bz2" || F.Type == "lzma")
{
Pos = Tmp-1;
continue;
diff --git a/apt-pkg/deb/debsrcrecords.h b/apt-pkg/deb/debsrcrecords.h
index f899993df..8b1237ccd 100644
--- a/apt-pkg/deb/debsrcrecords.h
+++ b/apt-pkg/deb/debsrcrecords.h
@@ -11,9 +11,6 @@
#ifndef PKGLIB_DEBSRCRECORDS_H
#define PKGLIB_DEBSRCRECORDS_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/debsrcrecords.h"
-#endif
#include <apt-pkg/srcrecords.h>
#include <apt-pkg/tagfile.h>
@@ -24,9 +21,10 @@ class debSrcRecordParser : public pkgSrcRecords::Parser
FileFd Fd;
pkgTagFile Tags;
pkgTagSection Sect;
- char Buffer[10000];
char *StaticBinList[400];
unsigned long iOffset;
+ char *Buffer;
+ unsigned int BufSize;
public:
@@ -49,10 +47,9 @@ class debSrcRecordParser : public pkgSrcRecords::Parser
};
virtual bool Files(vector<pkgSrcRecords::File> &F);
- debSrcRecordParser(string File,pkgIndexFile const *Index) :
- Parser(Index),
- Fd(File,FileFd::ReadOnly),
- Tags(&Fd,102400) {};
+ debSrcRecordParser(string File,pkgIndexFile const *Index)
+ : Parser(Index), Fd(File,FileFd::ReadOnly), Tags(&Fd,102400),
+ Buffer(0), BufSize(0) {}
};
#endif
diff --git a/apt-pkg/deb/debsystem.cc b/apt-pkg/deb/debsystem.cc
index 2d805ea6f..11a84f1c6 100644
--- a/apt-pkg/deb/debsystem.cc
+++ b/apt-pkg/deb/debsystem.cc
@@ -10,10 +10,6 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/debsystem.h"
-#endif
-
#include <apt-pkg/debsystem.h>
#include <apt-pkg/debversion.h>
#include <apt-pkg/debindexfile.h>
diff --git a/apt-pkg/deb/debsystem.h b/apt-pkg/deb/debsystem.h
index 84e57e74a..5f9995e5d 100644
--- a/apt-pkg/deb/debsystem.h
+++ b/apt-pkg/deb/debsystem.h
@@ -10,10 +10,6 @@
#ifndef PKGLIB_DEBSYSTEM_H
#define PKGLIB_DEBSYSTEM_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/debsystem.h"
-#endif
-
#include <apt-pkg/pkgsystem.h>
class debStatusIndex;
diff --git a/apt-pkg/deb/debversion.cc b/apt-pkg/deb/debversion.cc
index 064d8fa5b..ad45e9a44 100644
--- a/apt-pkg/deb/debversion.cc
+++ b/apt-pkg/deb/debversion.cc
@@ -11,9 +11,6 @@
/*}}}*/
// Include Files /*{{{*/
#define APT_COMPATIBILITY 986
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/debversion.h"
-#endif
#include <apt-pkg/debversion.h>
#include <apt-pkg/pkgcache.h>
diff --git a/apt-pkg/deb/debversion.h b/apt-pkg/deb/debversion.h
index 00a8832a8..56fb67887 100644
--- a/apt-pkg/deb/debversion.h
+++ b/apt-pkg/deb/debversion.h
@@ -12,9 +12,7 @@
#ifndef PKGLIB_DEBVERSION_H
#define PKGLIB_DEBVERSION_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/debversion.h"
-#endif
+
#include <apt-pkg/version.h>
diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc
index fe13614c5..34e166447 100644
--- a/apt-pkg/deb/dpkgpm.cc
+++ b/apt-pkg/deb/dpkgpm.cc
@@ -8,19 +8,18 @@
##################################################################### */
/*}}}*/
// Includes /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/dpkgpm.h"
-#endif
#include <apt-pkg/dpkgpm.h>
#include <apt-pkg/error.h>
#include <apt-pkg/configuration.h>
#include <apt-pkg/depcache.h>
#include <apt-pkg/strutl.h>
+#include <apti18n.h>
#include <apt-pkg/fileutl.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
+#include <sys/select.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
@@ -29,16 +28,25 @@
#include <sstream>
#include <map>
+#include <termios.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <pty.h>
+
#include <config.h>
#include <apti18n.h>
/*}}}*/
using namespace std;
+
+
// DPkgPM::pkgDPkgPM - Constructor /*{{{*/
// ---------------------------------------------------------------------
/* */
-pkgDPkgPM::pkgDPkgPM(pkgDepCache *Cache) : pkgPackageManager(Cache)
+pkgDPkgPM::pkgDPkgPM(pkgDepCache *Cache)
+ : pkgPackageManager(Cache), dpkgbuf_pos(0),
+ term_out(NULL), PackagesDone(0), PackagesTotal(0)
{
}
/*}}}*/
@@ -88,15 +96,6 @@ bool pkgDPkgPM::Remove(PkgIterator Pkg,bool Purge)
return true;
}
/*}}}*/
-// DPkgPM::RunScripts - Run a set of scripts /*{{{*/
-// ---------------------------------------------------------------------
-/* This looks for a list of script sto run from the configuration file,
- each one is run with system from a forked child. */
-bool pkgDPkgPM::RunScripts(const char *Cnf)
-{
- RunScripts(Cnf);
-}
- /*}}}*/
// DPkgPM::SendV2Pkgs - Send version 2 package info /*{{{*/
// ---------------------------------------------------------------------
/* This is part of the helper script communication interface, it sends
@@ -274,7 +273,240 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf)
return true;
}
+
/*}}}*/
+// DPkgPM::DoStdin - Read stdin and pass to slave pty /*{{{*/
+// ---------------------------------------------------------------------
+/*
+*/
+void pkgDPkgPM::DoStdin(int master)
+{
+ unsigned char input_buf[256] = {0,};
+ ssize_t len = read(0, input_buf, sizeof(input_buf));
+ if (len)
+ write(master, input_buf, len);
+ else
+ stdin_is_dev_null = true;
+}
+ /*}}}*/
+// DPkgPM::DoTerminalPty - Read the terminal pty and write log /*{{{*/
+// ---------------------------------------------------------------------
+/*
+ * read the terminal pty and write log
+ */
+void pkgDPkgPM::DoTerminalPty(int master)
+{
+ unsigned char term_buf[1024] = {0,0, };
+
+ ssize_t len=read(master, term_buf, sizeof(term_buf));
+ if(len == -1 && errno == EIO)
+ {
+ // this happens when the child is about to exit, we
+ // give it time to actually exit, otherwise we run
+ // into a race
+ usleep(500000);
+ return;
+ }
+ if(len <= 0)
+ return;
+ write(1, term_buf, len);
+ if(term_out)
+ fwrite(term_buf, len, sizeof(char), term_out);
+}
+ /*}}}*/
+// DPkgPM::ProcessDpkgStatusBuf /*{{{*/
+// ---------------------------------------------------------------------
+/*
+ */
+void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
+{
+ // the status we output
+ ostringstream status;
+
+ if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+ std::clog << "got from dpkg '" << line << "'" << std::endl;
+
+
+ /* dpkg sends strings like this:
+ 'status: <pkg>: <pkg qstate>'
+ errors look like this:
+ 'status: /var/cache/apt/archives/krecipes_0.8.1-0ubuntu1_i386.deb : error : trying to overwrite `/usr/share/doc/kde/HTML/en/krecipes/krectip.png', which is also in package krecipes-data
+ and conffile-prompt like this
+ 'status: conffile-prompt: conffile : 'current-conffile' 'new-conffile' useredited distedited
+
+ */
+ char* list[5];
+ // dpkg sends multiline error messages sometimes (see
+ // #374195 for a example. we should support this by
+ // either patching dpkg to not send multiline over the
+ // statusfd or by rewriting the code here to deal with
+ // it. for now we just ignore it and not crash
+ TokSplitString(':', line, list, sizeof(list)/sizeof(list[0]));
+ if( list[0] == NULL || list[1] == NULL || list[2] == NULL)
+ {
+ if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+ std::clog << "ignoring line: not enough ':'" << std::endl;
+ return;
+ }
+ char *pkg = list[1];
+ char *action = _strstrip(list[2]);
+
+ if(strncmp(action,"error",strlen("error")) == 0)
+ {
+ status << "pmerror:" << list[1]
+ << ":" << (PackagesDone/float(PackagesTotal)*100.0)
+ << ":" << list[3]
+ << endl;
+ if(OutStatusFd > 0)
+ write(OutStatusFd, status.str().c_str(), status.str().size());
+ if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+ std::clog << "send: '" << status.str() << "'" << endl;
+ return;
+ }
+ if(strncmp(action,"conffile",strlen("conffile")) == 0)
+ {
+ status << "pmconffile:" << list[1]
+ << ":" << (PackagesDone/float(PackagesTotal)*100.0)
+ << ":" << list[3]
+ << endl;
+ if(OutStatusFd > 0)
+ write(OutStatusFd, status.str().c_str(), status.str().size());
+ if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+ std::clog << "send: '" << status.str() << "'" << endl;
+ return;
+ }
+
+ vector<struct DpkgState> &states = PackageOps[pkg];
+ const char *next_action = NULL;
+ if(PackageOpsDone[pkg] < states.size())
+ next_action = states[PackageOpsDone[pkg]].state;
+ // check if the package moved to the next dpkg state
+ if(next_action && (strcmp(action, next_action) == 0))
+ {
+ // only read the translation if there is actually a next
+ // action
+ const char *translation = _(states[PackageOpsDone[pkg]].str);
+ char s[200];
+ snprintf(s, sizeof(s), translation, pkg);
+
+ // we moved from one dpkg state to a new one, report that
+ PackageOpsDone[pkg]++;
+ PackagesDone++;
+ // build the status str
+ status << "pmstatus:" << pkg
+ << ":" << (PackagesDone/float(PackagesTotal)*100.0)
+ << ":" << s
+ << endl;
+ if(OutStatusFd > 0)
+ write(OutStatusFd, status.str().c_str(), status.str().size());
+ if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+ std::clog << "send: '" << status.str() << "'" << endl;
+ }
+ if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+ std::clog << "(parsed from dpkg) pkg: " << pkg
+ << " action: " << action << endl;
+}
+
+// DPkgPM::DoDpkgStatusFd /*{{{*/
+// ---------------------------------------------------------------------
+/*
+ */
+void pkgDPkgPM::DoDpkgStatusFd(int statusfd, int OutStatusFd)
+{
+ char *p, *q;
+ int len;
+
+ len=read(statusfd, &dpkgbuf[dpkgbuf_pos], sizeof(dpkgbuf)-dpkgbuf_pos);
+ dpkgbuf_pos += len;
+ if(len <= 0)
+ return;
+
+ // process line by line if we have a buffer
+ p = q = dpkgbuf;
+ while((q=(char*)memchr(p, '\n', dpkgbuf+dpkgbuf_pos-p)) != NULL)
+ {
+ *q = 0;
+ ProcessDpkgStatusLine(OutStatusFd, p);
+ p=q+1; // continue with next line
+ }
+
+ // now move the unprocessed bits (after the final \n that is now a 0x0)
+ // to the start and update dpkgbuf_pos
+ p = (char*)memrchr(dpkgbuf, 0, dpkgbuf_pos);
+ if(p == NULL)
+ return;
+
+ // we are interessted in the first char *after* 0x0
+ p++;
+
+ // move the unprocessed tail to the start and update pos
+ memmove(dpkgbuf, p, p-dpkgbuf);
+ dpkgbuf_pos = dpkgbuf+dpkgbuf_pos-p;
+}
+ /*}}}*/
+
+bool pkgDPkgPM::OpenLog()
+{
+ string logdir = _config->FindDir("Dir::Log");
+ if(not FileExists(logdir))
+ return _error->Error(_("Directory '%s' missing"), logdir.c_str());
+ string logfile_name = flCombine(logdir,
+ _config->Find("Dir::Log::Terminal"));
+ if (!logfile_name.empty())
+ {
+ term_out = fopen(logfile_name.c_str(),"a");
+ chmod(logfile_name.c_str(), 0600);
+ // output current time
+ char outstr[200];
+ time_t t = time(NULL);
+ struct tm *tmp = localtime(&t);
+ strftime(outstr, sizeof(outstr), "%F %T", tmp);
+ fprintf(term_out, "\nLog started: ");
+ fprintf(term_out, outstr);
+ fprintf(term_out, "\n");
+ }
+ return true;
+}
+
+bool pkgDPkgPM::CloseLog()
+{
+ if(term_out)
+ {
+ char outstr[200];
+ time_t t = time(NULL);
+ struct tm *tmp = localtime(&t);
+ strftime(outstr, sizeof(outstr), "%F %T", tmp);
+ fprintf(term_out, "Log ended: ");
+ fprintf(term_out, outstr);
+ fprintf(term_out, "\n");
+ fclose(term_out);
+ }
+ term_out = NULL;
+ return true;
+}
+
+/*{{{*/
+// This implements a racy version of pselect for those architectures
+// that don't have a working implementation.
+// FIXME: Probably can be removed on Lenny+1
+static int racy_pselect(int nfds, fd_set *readfds, fd_set *writefds,
+ fd_set *exceptfds, const struct timespec *timeout,
+ const sigset_t *sigmask)
+{
+ sigset_t origmask;
+ struct timeval tv;
+ int retval;
+
+ tv.tv_sec = timeout->tv_sec;
+ tv.tv_usec = timeout->tv_nsec/1000;
+
+ sigprocmask(SIG_SETMASK, sigmask, &origmask);
+ retval = select(nfds, readfds, writefds, exceptfds, &tv);
+ sigprocmask(SIG_SETMASK, &origmask, 0);
+ return retval;
+}
+/*}}}*/
+
// DPkgPM::Go - Run the sequence /*{{{*/
// ---------------------------------------------------------------------
/* This globs the operations and calls dpkg
@@ -295,49 +527,45 @@ bool pkgDPkgPM::Go(int OutStatusFd)
if (RunScriptsWithPkgs("DPkg::Pre-Install-Pkgs") == false)
return false;
- // prepare the progress reporting
- int Done = 0;
- int Total = 0;
// map the dpkg states to the operations that are performed
// (this is sorted in the same way as Item::Ops)
- static const struct DpkgState DpkgStatesOpMap[][5] = {
+ static const struct DpkgState DpkgStatesOpMap[][7] = {
// Install operation
{
- {"half-installed", _("Preparing %s")},
- {"unpacked", _("Unpacking %s") },
+ {"half-installed", N_("Preparing %s")},
+ {"unpacked", N_("Unpacking %s") },
{NULL, NULL}
},
// Configure operation
{
- {"unpacked",_("Preparing to configure %s") },
- {"half-configured", _("Configuring %s") },
- { "installed", _("Installed %s")},
+ {"unpacked",N_("Preparing to configure %s") },
+ {"half-configured", N_("Configuring %s") },
+#if 0
+ {"triggers-awaited", N_("Processing triggers for %s") },
+ {"triggers-pending", N_("Processing triggers for %s") },
+#endif
+ { "installed", N_("Installed %s")},
{NULL, NULL}
},
// Remove operation
{
- {"half-configured", _("Preparing for removal of %s")},
- {"half-installed", _("Removing %s")},
- {"config-files", _("Removed %s")},
+ {"half-configured", N_("Preparing for removal of %s")},
+#if 0
+ {"triggers-awaited", N_("Preparing for removal of %s")},
+ {"triggers-pending", N_("Preparing for removal of %s")},
+#endif
+ {"half-installed", N_("Removing %s")},
+ {"config-files", N_("Removed %s")},
{NULL, NULL}
},
// Purge operation
{
- {"config-files", _("Preparing to completely remove %s")},
- {"not-installed", _("Completely removed %s")},
+ {"config-files", N_("Preparing to completely remove %s")},
+ {"not-installed", N_("Completely removed %s")},
{NULL, NULL}
},
};
- // the dpkg states that the pkg will run through, the string is
- // the package, the vector contains the dpkg states that the package
- // will go through
- map<string,vector<struct DpkgState> > PackageOps;
- // the dpkg states that are already done; the string is the package
- // the int is the state that is already done (e.g. a package that is
- // going to be install is already in state "half-installed")
- map<string,int> PackageOpsDone;
-
// init the PackageOps map, go over the list of packages that
// that will be [installed|configured|removed|purged] and add
// them to the PackageOps map (the dpkg states it goes through)
@@ -349,10 +577,15 @@ bool pkgDPkgPM::Go(int OutStatusFd)
for(int i=0; (DpkgStatesOpMap[(*I).Op][i]).state != NULL; i++)
{
PackageOps[name].push_back(DpkgStatesOpMap[(*I).Op][i]);
- Total++;
+ PackagesTotal++;
}
}
+ stdin_is_dev_null = false;
+
+ // create log
+ OpenLog();
+
// this loop is runs once per operation
for (vector<Item>::iterator I = List.begin(); I != List.end();)
{
@@ -422,6 +655,8 @@ bool pkgDPkgPM::Go(int OutStatusFd)
case Item::Install:
Args[n++] = "--unpack";
Size += strlen(Args[n-1]);
+ Args[n++] = "--auto-deconfigure";
+ Size += strlen(Args[n-1]);
break;
}
@@ -465,7 +700,30 @@ bool pkgDPkgPM::Go(int OutStatusFd)
it doesn't die but we do! So we must also ignore it */
sighandler_t old_SIGQUIT = signal(SIGQUIT,SIG_IGN);
sighandler_t old_SIGINT = signal(SIGINT,SIG_IGN);
-
+
+ struct termios tt;
+ struct winsize win;
+ int master;
+ int slave;
+
+ // FIXME: setup sensible signal handling (*ick*)
+ tcgetattr(0, &tt);
+ ioctl(0, TIOCGWINSZ, (char *)&win);
+ if (openpty(&master, &slave, NULL, &tt, &win) < 0)
+ {
+ const char *s = _("Can not write log, openpty() "
+ "failed (/dev/pts not mounted?)\n");
+ fprintf(stderr, "%s",s);
+ fprintf(term_out, "%s",s);
+ master = slave = -1;
+ } else {
+ struct termios rtt;
+ rtt = tt;
+ cfmakeraw(&rtt);
+ rtt.c_lflag &= ~ECHO;
+ tcsetattr(0, TCSAFLUSH, &rtt);
+ }
+
// Fork dpkg
pid_t Child;
_config->Set("APT::Keep-Fds::",fd[1]);
@@ -474,8 +732,18 @@ bool pkgDPkgPM::Go(int OutStatusFd)
// This is the child
if (Child == 0)
{
+ if(slave >= 0 && master >= 0)
+ {
+ setsid();
+ ioctl(slave, TIOCSCTTY, 0);
+ close(master);
+ dup2(slave, 0);
+ dup2(slave, 1);
+ dup2(slave, 2);
+ close(slave);
+ }
close(fd[0]); // close the read end of the pipe
-
+
if (chdir(_config->FindDir("DPkg::Run-Directory","/").c_str()) != 0)
_exit(100);
@@ -494,10 +762,11 @@ bool pkgDPkgPM::Go(int OutStatusFd)
if (fcntl(STDIN_FILENO,F_SETFL,Flags & (~(long)O_NONBLOCK)) < 0)
_exit(100);
}
-
+
+
/* No Job Control Stop Env is a magic dpkg var that prevents it
from using sigstop */
- putenv("DPKG_NO_TSTP=yes");
+ putenv((char *)"DPKG_NO_TSTP=yes");
execvp(Args[0],(char **)Args);
cerr << "Could not exec dpkg!" << endl;
_exit(100);
@@ -511,16 +780,22 @@ bool pkgDPkgPM::Go(int OutStatusFd)
// we read from dpkg here
int _dpkgin = fd[0];
- fcntl(_dpkgin, F_SETFL, O_NONBLOCK);
close(fd[1]); // close the write end of the pipe
- // the read buffers for the communication with dpkg
- char line[1024] = {0,};
- char buf[2] = {0,0};
-
// the result of the waitpid call
int res;
-
+ if(slave > 0)
+ close(slave);
+
+ // setups fds
+ fd_set rfds;
+ struct timespec tv;
+ sigset_t sigmask;
+ sigset_t original_sigmask;
+ sigemptyset(&sigmask);
+ sigprocmask(SIG_BLOCK,&sigmask,&original_sigmask);
+
+ int select_ret;
while ((res=waitpid(Child,&Status, WNOHANG)) != Child) {
if(res < 0) {
// FIXME: move this to a function or something, looks ugly here
@@ -534,128 +809,76 @@ bool pkgDPkgPM::Go(int OutStatusFd)
signal(SIGINT,old_SIGINT);
return _error->Errno("waitpid","Couldn't wait for subprocess");
}
-
- // read a single char, make sure that the read can't block
- // (otherwise we may leave zombies)
- int len = read(_dpkgin, buf, 1);
- // nothing to read, wait a bit for more
- if(len <= 0)
- {
- usleep(1000);
- continue;
- }
+ // wait for input or output here
+ FD_ZERO(&rfds);
+ if (!stdin_is_dev_null)
+ FD_SET(0, &rfds);
+ FD_SET(_dpkgin, &rfds);
+ if(master >= 0)
+ FD_SET(master, &rfds);
+ tv.tv_sec = 1;
+ tv.tv_nsec = 0;
+ select_ret = pselect(max(master, _dpkgin)+1, &rfds, NULL, NULL,
+ &tv, &original_sigmask);
+ if (select_ret < 0 && (errno == EINVAL || errno == ENOSYS))
+ select_ret = racy_pselect(max(master, _dpkgin)+1, &rfds, NULL,
+ NULL, &tv, &original_sigmask);
+ if (select_ret == 0)
+ continue;
+ else if (select_ret < 0 && errno == EINTR)
+ continue;
+ else if (select_ret < 0)
+ {
+ perror("select() returned error");
+ continue;
+ }
- // sanity check (should never happen)
- if(strlen(line) >= sizeof(line)-10)
- {
- _error->Error("got a overlong line from dpkg: '%s'",line);
- line[0]=0;
- }
- // append to line, check if we got a complete line
- strcat(line, buf);
- if(buf[0] != '\n')
- continue;
-
- if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
- std::clog << "got from dpkg '" << line << "'" << std::endl;
-
- // the status we output
- ostringstream status;
-
- /* dpkg sends strings like this:
- 'status: <pkg>: <pkg qstate>'
- errors look like this:
- 'status: /var/cache/apt/archives/krecipes_0.8.1-0ubuntu1_i386.deb : error : trying to overwrite `/usr/share/doc/kde/HTML/en/krecipes/krectip.png', which is also in package krecipes-data
- and conffile-prompt like this
- 'status: conffile-prompt: conffile : 'current-conffile' 'new-conffile' useredited distedited
-
- */
- char* list[5];
- TokSplitString(':', line, list, sizeof(list)/sizeof(list[0]));
- char *pkg = list[1];
- char *action = _strstrip(list[2]);
-
- if(strncmp(action,"error",strlen("error")) == 0)
- {
- status << "pmerror:" << list[1]
- << ":" << (Done/float(Total)*100.0)
- << ":" << list[3]
- << endl;
- if(OutStatusFd > 0)
- write(OutStatusFd, status.str().c_str(), status.str().size());
- line[0]=0;
- if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
- std::clog << "send: '" << status.str() << "'" << endl;
- continue;
- }
- if(strncmp(action,"conffile",strlen("conffile")) == 0)
- {
- status << "pmconffile:" << list[1]
- << ":" << (Done/float(Total)*100.0)
- << ":" << list[3]
- << endl;
- if(OutStatusFd > 0)
- write(OutStatusFd, status.str().c_str(), status.str().size());
- line[0]=0;
- if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
- std::clog << "send: '" << status.str() << "'" << endl;
- continue;
- }
-
- vector<struct DpkgState> &states = PackageOps[pkg];
- const char *next_action = NULL;
- if(PackageOpsDone[pkg] < states.size())
- next_action = states[PackageOpsDone[pkg]].state;
- // check if the package moved to the next dpkg state
- if(next_action && (strcmp(action, next_action) == 0))
- {
- // only read the translation if there is actually a next
- // action
- const char *translation = states[PackageOpsDone[pkg]].str;
- char s[200];
- snprintf(s, sizeof(s), translation, pkg);
-
- // we moved from one dpkg state to a new one, report that
- PackageOpsDone[pkg]++;
- Done++;
- // build the status str
- status << "pmstatus:" << pkg
- << ":" << (Done/float(Total)*100.0)
- << ":" << s
- << endl;
- if(OutStatusFd > 0)
- write(OutStatusFd, status.str().c_str(), status.str().size());
- if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
- std::clog << "send: '" << status.str() << "'" << endl;
-
- }
- if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
- std::clog << "(parsed from dpkg) pkg: " << pkg
- << " action: " << action << endl;
-
- // reset the line buffer
- line[0]=0;
+ if(master >= 0 && FD_ISSET(master, &rfds))
+ DoTerminalPty(master);
+ if(master >= 0 && FD_ISSET(0, &rfds))
+ DoStdin(master);
+ if(FD_ISSET(_dpkgin, &rfds))
+ DoDpkgStatusFd(_dpkgin, OutStatusFd);
}
close(_dpkgin);
// Restore sig int/quit
signal(SIGQUIT,old_SIGQUIT);
signal(SIGINT,old_SIGINT);
+
+ if(master >= 0)
+ {
+ tcsetattr(0, TCSAFLUSH, &tt);
+ close(master);
+ }
// Check for an error code.
if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
{
- RunScripts("DPkg::Post-Invoke");
- if (WIFSIGNALED(Status) != 0 && WTERMSIG(Status) == SIGSEGV)
- return _error->Error("Sub-process %s received a segmentation fault.",Args[0]);
-
- if (WIFEXITED(Status) != 0)
- return _error->Error("Sub-process %s returned an error code (%u)",Args[0],WEXITSTATUS(Status));
+ // if it was set to "keep-dpkg-runing" then we won't return
+ // here but keep the loop going and just report it as a error
+ // for later
+ bool stopOnError = _config->FindB("Dpkg::StopOnError",true);
- return _error->Error("Sub-process %s exited unexpectedly",Args[0]);
+ if(stopOnError)
+ RunScripts("DPkg::Post-Invoke");
+
+ if (WIFSIGNALED(Status) != 0 && WTERMSIG(Status) == SIGSEGV)
+ _error->Error("Sub-process %s received a segmentation fault.",Args[0]);
+ else if (WIFEXITED(Status) != 0)
+ _error->Error("Sub-process %s returned an error code (%u)",Args[0],WEXITSTATUS(Status));
+ else
+ _error->Error("Sub-process %s exited unexpectedly",Args[0]);
+
+ if(stopOnError)
+ {
+ CloseLog();
+ return false;
+ }
}
}
+ CloseLog();
if (RunScripts("DPkg::Post-Invoke") == false)
return false;
diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h
index 2ff8a9ac7..ebc7e32bf 100644
--- a/apt-pkg/deb/dpkgpm.h
+++ b/apt-pkg/deb/dpkgpm.h
@@ -10,27 +10,47 @@
#ifndef PKGLIB_DPKGPM_H
#define PKGLIB_DPKGPM_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/dpkgpm.h"
-#endif
-
#include <apt-pkg/packagemanager.h>
#include <vector>
+#include <map>
#include <stdio.h>
using std::vector;
+using std::map;
+
class pkgDPkgPM : public pkgPackageManager
{
+ private:
+
+ bool stdin_is_dev_null;
+
+ // the buffer we use for the dpkg status-fd reading
+ char dpkgbuf[1024];
+ int dpkgbuf_pos;
+ FILE *term_out;
+
protected:
- // used for progress reporting
+ // progress reporting
struct DpkgState
{
const char *state; // the dpkg state (e.g. "unpack")
const char *str; // the human readable translation of the state
};
-
+
+ // the dpkg states that the pkg will run through, the string is
+ // the package, the vector contains the dpkg states that the package
+ // will go through
+ map<string,vector<struct DpkgState> > PackageOps;
+ // the dpkg states that are already done; the string is the package
+ // the int is the state that is already done (e.g. a package that is
+ // going to be install is already in state "half-installed")
+ map<string,unsigned int> PackageOpsDone;
+ // progress reporting
+ unsigned int PackagesDone;
+ unsigned int PackagesTotal;
+
struct Item
{
enum Ops {Install, Configure, Remove, Purge} Op;
@@ -44,10 +64,19 @@ class pkgDPkgPM : public pkgPackageManager
vector<Item> List;
// Helpers
- bool RunScripts(const char *Cnf);
bool RunScriptsWithPkgs(const char *Cnf);
bool SendV2Pkgs(FILE *F);
+
+ // dpkg log
+ bool OpenLog();
+ bool CloseLog();
+ // input processing
+ void DoStdin(int master);
+ void DoTerminalPty(int master);
+ void DoDpkgStatusFd(int statusfd, int OutStatusFd);
+ void ProcessDpkgStatusLine(int OutStatusFd, char *line);
+
// The Actuall installation implementation
virtual bool Install(PkgIterator Pkg,string File);
virtual bool Configure(PkgIterator Pkg);
diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc
index 58d1d25e5..c21872449 100644
--- a/apt-pkg/depcache.cc
+++ b/apt-pkg/depcache.cc
@@ -8,24 +8,80 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/depcache.h"
-#endif
#include <apt-pkg/depcache.h>
#include <apt-pkg/version.h>
#include <apt-pkg/error.h>
#include <apt-pkg/sptr.h>
#include <apt-pkg/algorithms.h>
+
+#include <apt-pkg/fileutl.h>
#include <apt-pkg/configuration.h>
+#include <apt-pkg/pkgsystem.h>
+#include <apt-pkg/tagfile.h>
+
+#include <iostream>
+#include <sstream>
+#include <set>
+
+#include <sys/stat.h>
#include <apti18n.h>
- /*}}}*/
+
+// helper for Install-Recommends-Sections and Never-MarkAuto-Sections
+static bool
+ConfigValueInSubTree(const char* SubTree, const char *needle)
+{
+ Configuration::Item const *Opts;
+ Opts = _config->Tree(SubTree);
+ if (Opts != 0 && Opts->Child != 0)
+ {
+ Opts = Opts->Child;
+ for (; Opts != 0; Opts = Opts->Next)
+ {
+ if (Opts->Value.empty() == true)
+ continue;
+ if (strcmp(needle, Opts->Value.c_str()) == 0)
+ return true;
+ }
+ }
+ return false;
+}
+
+
+pkgDepCache::ActionGroup::ActionGroup(pkgDepCache &cache) :
+ cache(cache), released(false)
+{
+ ++cache.group_level;
+}
+
+void pkgDepCache::ActionGroup::release()
+{
+ if(!released)
+ {
+ if(cache.group_level == 0)
+ std::cerr << "W: Unbalanced action groups, expect badness" << std::endl;
+ else
+ {
+ --cache.group_level;
+
+ if(cache.group_level == 0)
+ cache.MarkAndSweep();
+ }
+
+ released = false;
+ }
+}
+
+pkgDepCache::ActionGroup::~ActionGroup()
+{
+ release();
+}
// DepCache::pkgDepCache - Constructors /*{{{*/
// ---------------------------------------------------------------------
/* */
pkgDepCache::pkgDepCache(pkgCache *pCache,Policy *Plcy) :
- Cache(pCache), PkgState(0), DepState(0)
+ group_level(0), Cache(pCache), PkgState(0), DepState(0)
{
delLocalPolicy = 0;
LocalPolicy = Plcy;
@@ -48,6 +104,10 @@ pkgDepCache::~pkgDepCache()
/* This allocats the extension buffers and initializes them. */
bool pkgDepCache::Init(OpProgress *Prog)
{
+ // Suppress mark updates during this operation (just in case) and
+ // run a mark operation when Init terminates.
+ ActionGroup actions(*this);
+
delete [] PkgState;
delete [] DepState;
PkgState = new StateCache[Head().PackageCount];
@@ -73,7 +133,7 @@ bool pkgDepCache::Init(OpProgress *Prog)
// Find the proper cache slot
StateCache &State = PkgState[I->ID];
State.iFlags = 0;
-
+
// Figure out the install version
State.CandidateVer = GetCandidateVer(I);
State.InstallVer = I.CurrentVer();
@@ -95,11 +155,133 @@ bool pkgDepCache::Init(OpProgress *Prog)
if(Prog != 0)
Prog->Done();
-
+
return true;
}
/*}}}*/
+bool pkgDepCache::readStateFile(OpProgress *Prog)
+{
+ FileFd state_file;
+ string state = _config->FindDir("Dir::State") + "extended_states";
+ if(FileExists(state)) {
+ state_file.Open(state, FileFd::ReadOnly);
+ int file_size = state_file.Size();
+ if(Prog != NULL)
+ Prog->OverallProgress(0, file_size, 1,
+ _("Reading state information"));
+
+ pkgTagFile tagfile(&state_file);
+ pkgTagSection section;
+ int amt=0;
+ while(tagfile.Step(section)) {
+ string pkgname = section.FindS("Package");
+ pkgCache::PkgIterator pkg=Cache->FindPkg(pkgname);
+ // Silently ignore unknown packages and packages with no actual
+ // version.
+ if(!pkg.end() && !pkg.VersionList().end()) {
+ short reason = section.FindI("Auto-Installed", 0);
+ if(reason > 0)
+ PkgState[pkg->ID].Flags |= Flag::Auto;
+ if(_config->FindB("Debug::pkgAutoRemove",false))
+ std::cout << "Auto-Installed : " << pkgname << std::endl;
+ amt+=section.size();
+ if(Prog != NULL)
+ Prog->OverallProgress(amt, file_size, 1,
+ _("Reading state information"));
+ }
+ if(Prog != NULL)
+ Prog->OverallProgress(file_size, file_size, 1,
+ _("Reading state information"));
+ }
+ }
+
+ return true;
+}
+
+bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly)
+{
+ if(_config->FindB("Debug::pkgAutoRemove",false))
+ std::clog << "pkgDepCache::writeStateFile()" << std::endl;
+
+ FileFd StateFile;
+ string state = _config->FindDir("Dir::State") + "extended_states";
+
+ // if it does not exist, create a empty one
+ if(!FileExists(state))
+ {
+ StateFile.Open(state, FileFd::WriteEmpty);
+ StateFile.Close();
+ }
+
+ // open it
+ if(!StateFile.Open(state, FileFd::ReadOnly))
+ return _error->Error(_("Failed to open StateFile %s"),
+ state.c_str());
+
+ FILE *OutFile;
+ string outfile = state + ".tmp";
+ if((OutFile = fopen(outfile.c_str(),"w")) == NULL)
+ return _error->Error(_("Failed to write temporary StateFile %s"),
+ outfile.c_str());
+
+ // first merge with the existing sections
+ pkgTagFile tagfile(&StateFile);
+ pkgTagSection section;
+ std::set<string> pkgs_seen;
+ const char *nullreorderlist[] = {0};
+ while(tagfile.Step(section)) {
+ string pkgname = section.FindS("Package");
+ // Silently ignore unknown packages and packages with no actual
+ // version.
+ pkgCache::PkgIterator pkg=Cache->FindPkg(pkgname);
+ if(pkg.end() || pkg.VersionList().end())
+ continue;
+ bool newAuto = (PkgState[pkg->ID].Flags & Flag::Auto);
+ if(_config->FindB("Debug::pkgAutoRemove",false))
+ std::clog << "Update exisiting AutoInstall info: "
+ << pkg.Name() << std::endl;
+ TFRewriteData rewrite[2];
+ rewrite[0].Tag = "Auto-Installed";
+ rewrite[0].Rewrite = newAuto ? "1" : "0";
+ rewrite[0].NewTag = 0;
+ rewrite[1].Tag = 0;
+ TFRewrite(OutFile, section, nullreorderlist, rewrite);
+ fprintf(OutFile,"\n");
+ pkgs_seen.insert(pkgname);
+ }
+
+ // then write the ones we have not seen yet
+ std::ostringstream ostr;
+ for(pkgCache::PkgIterator pkg=Cache->PkgBegin(); !pkg.end(); pkg++) {
+ if(PkgState[pkg->ID].Flags & Flag::Auto) {
+ if (pkgs_seen.find(pkg.Name()) != pkgs_seen.end()) {
+ if(_config->FindB("Debug::pkgAutoRemove",false))
+ std::clog << "Skipping already written " << pkg.Name() << std::endl;
+ continue;
+ }
+ // skip not installed ones if requested
+ if(InstalledOnly && pkg->CurrentVer == 0)
+ continue;
+ if(_config->FindB("Debug::pkgAutoRemove",false))
+ std::clog << "Writing new AutoInstall: "
+ << pkg.Name() << std::endl;
+ ostr.str(string(""));
+ ostr << "Package: " << pkg.Name()
+ << "\nAuto-Installed: 1\n\n";
+ fprintf(OutFile,ostr.str().c_str());
+ fprintf(OutFile,"\n");
+ }
+ }
+ fclose(OutFile);
+
+ // move the outfile over the real file and set permissions
+ rename(outfile.c_str(), state.c_str());
+ chmod(state.c_str(), 0644);
+
+ return true;
+}
+
// DepCache::CheckDep - Checks a single dependency /*{{{*/
// ---------------------------------------------------------------------
/* This first checks the dependency against the main target package and
@@ -114,7 +296,7 @@ bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res)
we allow it anyhow because dpkg does. Technically it is a packaging
bug. Conflicts may never self match */
if (Dep.TargetPkg() != Dep.ParentPkg() ||
- (Dep->Type != Dep::Conflicts && Dep->Type != Dep::Obsoletes))
+ (Dep->Type != Dep::Conflicts && Dep->Type != Dep::DpkgBreaks && Dep->Type != Dep::Obsoletes))
{
PkgIterator Pkg = Dep.TargetPkg();
// Check the base package
@@ -144,7 +326,8 @@ bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res)
{
/* Provides may never be applied against the same package if it is
a conflicts. See the comment above. */
- if (P.OwnerPkg() == Pkg && Dep->Type == Dep::Conflicts)
+ if (P.OwnerPkg() == Pkg &&
+ (Dep->Type == Dep::Conflicts || Dep->Type == Dep::DpkgBreaks))
continue;
// Check if the provides is a hit
@@ -240,9 +423,11 @@ void pkgDepCache::AddStates(const PkgIterator &Pkg,int Add)
{
StateCache &State = PkgState[Pkg->ID];
- // The Package is broken
+ // The Package is broken (either minimal dep or policy dep)
if ((State.DepState & DepInstMin) != DepInstMin)
iBrokenCount += Add;
+ if ((State.DepState & DepInstPolicy) != DepInstPolicy)
+ iPolicyBrokenCount += Add;
// Bad state
if (Pkg.State() != PkgIterator::NeedsNothing)
@@ -296,7 +481,9 @@ void pkgDepCache::BuildGroupOrs(VerIterator const &V)
/* Invert for Conflicts. We have to do this twice to get the
right sense for a conflicts group */
- if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
+ if (D->Type == Dep::Conflicts ||
+ D->Type == Dep::DpkgBreaks ||
+ D->Type == Dep::Obsoletes)
State = ~State;
// Add to the group if we are within an or..
@@ -307,7 +494,9 @@ void pkgDepCache::BuildGroupOrs(VerIterator const &V)
Group = 0;
// Invert for Conflicts
- if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
+ if (D->Type == Dep::Conflicts ||
+ D->Type == Dep::DpkgBreaks ||
+ D->Type == Dep::Obsoletes)
State = ~State;
}
}
@@ -440,7 +629,9 @@ void pkgDepCache::Update(OpProgress *Prog)
Group = 0;
// Invert for Conflicts
- if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
+ if (D->Type == Dep::Conflicts ||
+ D->Type == Dep::DpkgBreaks ||
+ D->Type == Dep::Obsoletes)
State = ~State;
}
}
@@ -453,12 +644,14 @@ void pkgDepCache::Update(OpProgress *Prog)
if (Prog != 0)
Prog->Progress(Done);
+
+ readStateFile(Prog);
}
/*}}}*/
// DepCache::Update - Update the deps list of a package /*{{{*/
// ---------------------------------------------------------------------
/* This is a helper for update that only does the dep portion of the scan.
- It is mainly ment to scan reverse dependencies. */
+ It is mainly meant to scan reverse dependencies. */
void pkgDepCache::Update(DepIterator D)
{
// Update the reverse deps
@@ -468,7 +661,9 @@ void pkgDepCache::Update(DepIterator D)
State = DependencyState(D);
// Invert for Conflicts
- if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
+ if (D->Type == Dep::Conflicts ||
+ D->Type == Dep::DpkgBreaks ||
+ D->Type == Dep::Obsoletes)
State = ~State;
RemoveStates(D.ParentPkg());
@@ -510,7 +705,7 @@ void pkgDepCache::Update(PkgIterator const &Pkg)
// DepCache::MarkKeep - Put the package in the keep state /*{{{*/
// ---------------------------------------------------------------------
/* */
-void pkgDepCache::MarkKeep(PkgIterator const &Pkg,bool Soft)
+void pkgDepCache::MarkKeep(PkgIterator const &Pkg, bool Soft, bool FromUser)
{
// Simplifies other routines.
if (Pkg.end() == true)
@@ -522,6 +717,9 @@ void pkgDepCache::MarkKeep(PkgIterator const &Pkg,bool Soft)
Pkg.CurrentVer().Downloadable() == false)
return;
+ /** \todo Can this be moved later in the method? */
+ ActionGroup group(*this);
+
/* We changed the soft state all the time so the UI is a bit nicer
to use */
StateCache &P = PkgState[Pkg->ID];
@@ -537,8 +735,17 @@ void pkgDepCache::MarkKeep(PkgIterator const &Pkg,bool Soft)
// We dont even try to keep virtual packages..
if (Pkg->VersionList == 0)
return;
-
- P.Flags &= ~Flag::Auto;
+#if 0 // reseting the autoflag here means we lose the
+ // auto-mark information if a user selects a package for removal
+ // but changes his mind then and sets it for keep again
+ // - this makes sense as default when all Garbage dependencies
+ // are automatically marked for removal (as aptitude does).
+ // setting a package for keep then makes it no longer autoinstalled
+ // for all other use-case this action is rather suprising
+ if(FromUser && !P.Marked)
+ P.Flags &= ~Flag::Auto;
+#endif
+
RemoveSizes(Pkg);
RemoveStates(Pkg);
@@ -564,6 +771,8 @@ void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge)
if (Pkg.end() == true)
return;
+ ActionGroup group(*this);
+
// Check that it is not already marked for delete
StateCache &P = PkgState[Pkg->ID];
P.iFlags &= ~(AutoKept | Purge);
@@ -586,7 +795,6 @@ void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge)
else
P.Mode = ModeDelete;
P.InstallVer = 0;
- P.Flags &= Flag::Auto;
AddStates(Pkg);
Update(Pkg);
@@ -597,7 +805,8 @@ void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge)
// ---------------------------------------------------------------------
/* */
void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
- unsigned long Depth)
+ unsigned long Depth, bool FromUser,
+ bool ForceImportantDeps)
{
if (Depth > 100)
return;
@@ -606,26 +815,27 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
if (Pkg.end() == true)
return;
+ ActionGroup group(*this);
+
/* Check that it is not already marked for install and that it can be
installed */
StateCache &P = PkgState[Pkg->ID];
P.iFlags &= ~AutoKept;
- if (P.InstBroken() == false && (P.Mode == ModeInstall ||
+ if ((P.InstPolicyBroken() == false && P.InstBroken() == false) &&
+ (P.Mode == ModeInstall ||
P.CandidateVer == (Version *)Pkg.CurrentVer()))
{
if (P.CandidateVer == (Version *)Pkg.CurrentVer() && P.InstallVer == 0)
- MarkKeep(Pkg);
+ MarkKeep(Pkg, false, FromUser);
return;
}
// See if there is even any possible instalation candidate
if (P.CandidateVer == 0)
return;
-
// We dont even try to install virtual packages..
if (Pkg->VersionList == 0)
return;
-
/* Target the candidate version and remove the autoflag. We reset the
autoflag below if this was called recursively. Otherwise the user
should have the ability to de-auto a package by changing its state */
@@ -634,7 +844,20 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
P.Mode = ModeInstall;
P.InstallVer = P.CandidateVer;
- P.Flags &= ~Flag::Auto;
+
+ if(FromUser)
+ {
+ // Set it to manual if it's a new install or cancelling the
+ // removal of a garbage package.
+ if(P.Status == 2 || (!Pkg.CurrentVer().end() && !P.Marked))
+ P.Flags &= ~Flag::Auto;
+ }
+ else
+ {
+ // Set it to auto if this is a new install.
+ if(P.Status == 2)
+ P.Flags |= Flag::Auto;
+ }
if (P.CandidateVer == (Version *)Pkg.CurrentVer())
P.Mode = ModeKeep;
@@ -666,10 +889,43 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
/* Check if this dep should be consider for install. If it is a user
defined important dep and we are installed a new package then
- it will be installed. Otherwise we only worry about critical deps */
+ it will be installed. Otherwise we only check for important
+ deps that have changed from the installed version
+ */
if (IsImportantDep(Start) == false)
continue;
- if (Pkg->CurrentVer != 0 && Start.IsCritical() == false)
+
+ /* check if any ImportantDep() (but not Critial) where added
+ * since we installed the package
+ */
+ bool isNewImportantDep = false;
+ if(!ForceImportantDeps && !Start.IsCritical())
+ {
+ bool found=false;
+ VerIterator instVer = Pkg.CurrentVer();
+ if(!instVer.end())
+ {
+ for (DepIterator D = instVer.DependsList(); D.end() != true; D++)
+ {
+ //FIXME: deal better with or-groups(?)
+ DepIterator LocalStart = D;
+
+ if(IsImportantDep(D) && Start.TargetPkg() == D.TargetPkg())
+ found=true;
+ }
+ // this is a new dep if it was not found to be already
+ // a important dep of the installed pacakge
+ isNewImportantDep = !found;
+ }
+ }
+ if(isNewImportantDep)
+ if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
+ std::clog << "new important dependency: "
+ << Start.TargetPkg().Name() << std::endl;
+
+ // skip important deps if the package is already installed
+ if (Pkg->CurrentVer != 0 && Start.IsCritical() == false
+ && !isNewImportantDep && !ForceImportantDeps)
continue;
/* If we are in an or group locate the first or that can
@@ -680,7 +936,8 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
/* This bit is for processing the possibilty of an install/upgrade
fixing the problem */
SPtrArray<Version *> List = Start.AllTargets();
- if ((DepState[Start->ID] & DepCVer) == DepCVer)
+ if (Start->Type != Dep::DpkgBreaks &&
+ (DepState[Start->ID] & DepCVer) == DepCVer)
{
// Right, find the best version to install..
Version **Cur = List;
@@ -711,33 +968,47 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
}
}
- if (InstPkg.end() == false)
+ if (InstPkg.end() == false)
{
if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
std::clog << "Installing " << InstPkg.Name()
<< " as dep of " << Pkg.Name()
<< std::endl;
- MarkInstall(InstPkg,true,Depth + 1);
-
- // Set the autoflag, after MarkInstall because MarkInstall unsets it
- if (P->CurrentVer == 0)
- PkgState[InstPkg->ID].Flags |= Flag::Auto;
+ // now check if we should consider it a automatic dependency or not
+ if(Pkg.Section() && ConfigValueInSubTree("APT::Never-MarkAuto-Sections", Pkg.Section()))
+ {
+ if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
+ std::clog << "Setting NOT as auto-installed (direct dep of pkg in APT::Never-MarkAuto-Section)" << std::endl;
+ MarkInstall(InstPkg,true,Depth + 1, true);
+ }
+ else
+ {
+ // mark automatic dependency
+ MarkInstall(InstPkg,true,Depth + 1, false, ForceImportantDeps);
+ // Set the autoflag, after MarkInstall because MarkInstall unsets it
+ if (P->CurrentVer == 0)
+ PkgState[InstPkg->ID].Flags |= Flag::Auto;
+ }
}
-
continue;
}
-
+
/* For conflicts we just de-install the package and mark as auto,
- Conflicts may not have or groups */
- if (Start->Type == Dep::Conflicts || Start->Type == Dep::Obsoletes)
+ Conflicts may not have or groups. For dpkg's Breaks we try to
+ upgrade the package. */
+ if (Start->Type == Dep::Conflicts || Start->Type == Dep::Obsoletes ||
+ Start->Type == Dep::DpkgBreaks)
{
for (Version **I = List; *I != 0; I++)
{
VerIterator Ver(*this,*I);
PkgIterator Pkg = Ver.ParentPkg();
-
- MarkDelete(Pkg);
- PkgState[Pkg->ID].Flags |= Flag::Auto;
+
+ if (Start->Type != Dep::DpkgBreaks)
+ MarkDelete(Pkg);
+ else
+ if (PkgState[Pkg->ID].CandidateVer != *I)
+ MarkInstall(Pkg,true,Depth + 1, false, ForceImportantDeps);
}
continue;
}
@@ -749,6 +1020,8 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
/* */
void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To)
{
+ ActionGroup group(*this);
+
RemoveSizes(Pkg);
RemoveStates(Pkg);
@@ -767,9 +1040,11 @@ void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To)
/* */
void pkgDepCache::SetCandidateVersion(VerIterator TargetVer)
{
+ ActionGroup group(*this);
+
pkgCache::PkgIterator Pkg = TargetVer.ParentPkg();
StateCache &P = PkgState[Pkg->ID];
-
+
RemoveSizes(Pkg);
RemoveStates(Pkg);
@@ -782,6 +1057,18 @@ void pkgDepCache::SetCandidateVersion(VerIterator TargetVer)
Update(Pkg);
AddSizes(Pkg);
}
+
+void pkgDepCache::MarkAuto(const PkgIterator &Pkg, bool Auto)
+{
+ StateCache &state = PkgState[Pkg->ID];
+
+ ActionGroup group(*this);
+
+ if(Auto)
+ state.Flags |= Flag::Auto;
+ else
+ state.Flags &= ~Flag::Auto;
+}
/*}}}*/
// StateCache::Update - Compute the various static display things /*{{{*/
// ---------------------------------------------------------------------
@@ -864,11 +1151,249 @@ pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator Pkg)
return Last;
}
/*}}}*/
+
// Policy::IsImportantDep - True if the dependency is important /*{{{*/
// ---------------------------------------------------------------------
/* */
bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep)
{
- return Dep.IsCritical();
+ if(Dep.IsCritical())
+ return true;
+ else if(Dep->Type == pkgCache::Dep::Recommends)
+ {
+ if ( _config->FindB("APT::Install-Recommends", false))
+ return true;
+ // we suport a special mode to only install-recommends for certain
+ // sections
+ // FIXME: this is a meant as a temporarly solution until the
+ // recommends are cleaned up
+ const char *sec = Dep.ParentVer().Section();
+ if (sec && ConfigValueInSubTree("APT::Install-Recommends-Sections", sec))
+ return true;
+ }
+ else if(Dep->Type == pkgCache::Dep::Suggests)
+ return _config->FindB("APT::Install-Suggests", false);
+
+ return false;
}
/*}}}*/
+
+pkgDepCache::DefaultRootSetFunc::DefaultRootSetFunc()
+ : constructedSuccessfully(false)
+{
+ Configuration::Item const *Opts;
+ Opts = _config->Tree("APT::NeverAutoRemove");
+ if (Opts != 0 && Opts->Child != 0)
+ {
+ Opts = Opts->Child;
+ for (; Opts != 0; Opts = Opts->Next)
+ {
+ if (Opts->Value.empty() == true)
+ continue;
+
+ regex_t *p = new regex_t;
+ if(regcomp(p,Opts->Value.c_str(),
+ REG_EXTENDED | REG_ICASE | REG_NOSUB) != 0)
+ {
+ regfree(p);
+ delete p;
+ _error->Error("Regex compilation error for APT::NeverAutoRemove");
+ return;
+ }
+
+ rootSetRegexp.push_back(p);
+ }
+ }
+
+ constructedSuccessfully = true;
+}
+
+pkgDepCache::DefaultRootSetFunc::~DefaultRootSetFunc()
+{
+ for(unsigned int i = 0; i < rootSetRegexp.size(); i++)
+ {
+ regfree(rootSetRegexp[i]);
+ delete rootSetRegexp[i];
+ }
+}
+
+
+bool pkgDepCache::DefaultRootSetFunc::InRootSet(const pkgCache::PkgIterator &pkg)
+{
+ for(unsigned int i = 0; i < rootSetRegexp.size(); i++)
+ if (regexec(rootSetRegexp[i], pkg.Name(), 0, 0, 0) == 0)
+ return true;
+
+ return false;
+}
+
+pkgDepCache::InRootSetFunc *pkgDepCache::GetRootSetFunc()
+{
+ DefaultRootSetFunc *f = new DefaultRootSetFunc;
+ if(f->wasConstructedSuccessfully())
+ return f;
+ else
+ {
+ delete f;
+ return NULL;
+ }
+}
+
+bool pkgDepCache::MarkFollowsRecommends()
+{
+ return _config->FindB("APT::AutoRemove::RecommendsImportant", true);
+}
+
+bool pkgDepCache::MarkFollowsSuggests()
+{
+ return _config->FindB("APT::AutoRemove::SuggestsImportant", false);
+}
+
+// the main mark algorithm
+bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
+{
+ bool follow_recommends;
+ bool follow_suggests;
+
+ // init the states
+ for(PkgIterator p = PkgBegin(); !p.end(); ++p)
+ {
+ PkgState[p->ID].Marked = false;
+ PkgState[p->ID].Garbage = false;
+
+ // debug output
+ if(_config->FindB("Debug::pkgAutoRemove",false)
+ && PkgState[p->ID].Flags & Flag::Auto)
+ std::clog << "AutoDep: " << p.Name() << std::endl;
+ }
+
+ // init vars
+ follow_recommends = MarkFollowsRecommends();
+ follow_suggests = MarkFollowsSuggests();
+
+
+
+ // do the mark part, this is the core bit of the algorithm
+ for(PkgIterator p = PkgBegin(); !p.end(); ++p)
+ {
+ if(!(PkgState[p->ID].Flags & Flag::Auto) ||
+ (p->Flags & Flag::Essential) ||
+ userFunc.InRootSet(p))
+
+ {
+ // the package is installed (and set to keep)
+ if(PkgState[p->ID].Keep() && !p.CurrentVer().end())
+ MarkPackage(p, p.CurrentVer(),
+ follow_recommends, follow_suggests);
+ // the package is to be installed
+ else if(PkgState[p->ID].Install())
+ MarkPackage(p, PkgState[p->ID].InstVerIter(*this),
+ follow_recommends, follow_suggests);
+ }
+ }
+
+ return true;
+}
+
+// mark a single package in Mark-and-Sweep
+void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
+ const pkgCache::VerIterator &ver,
+ bool follow_recommends,
+ bool follow_suggests)
+{
+ pkgDepCache::StateCache &state = PkgState[pkg->ID];
+ VerIterator currver = pkg.CurrentVer();
+ VerIterator candver = state.CandidateVerIter(*this);
+ VerIterator instver = state.InstVerIter(*this);
+
+#if 0
+ // If a package was garbage-collected but is now being marked, we
+ // should re-select it
+ // For cases when a pkg is set to upgrade and this trigger the
+ // removal of a no-longer used dependency. if the pkg is set to
+ // keep again later it will result in broken deps
+ if(state.Delete() && state.RemoveReason = Unused)
+ {
+ if(ver==candver)
+ mark_install(pkg, false, false, NULL);
+ else if(ver==pkg.CurrentVer())
+ MarkKeep(pkg, false, false);
+
+ instver=state.InstVerIter(*this);
+ }
+#endif
+
+ // For packages that are not going to be removed, ignore versions
+ // other than the InstVer. For packages that are going to be
+ // removed, ignore versions other than the current version.
+ if(!(ver == instver && !instver.end()) &&
+ !(ver == currver && instver.end() && !ver.end()))
+ return;
+
+ // if we are marked already we are done
+ if(state.Marked)
+ return;
+
+ //std::cout << "Setting Marked for: " << pkg.Name() << std::endl;
+ state.Marked=true;
+
+ if(!ver.end())
+ {
+ for(DepIterator d = ver.DependsList(); !d.end(); ++d)
+ {
+ if(d->Type == Dep::Depends ||
+ d->Type == Dep::PreDepends ||
+ (follow_recommends &&
+ d->Type == Dep::Recommends) ||
+ (follow_suggests &&
+ d->Type == Dep::Suggests))
+ {
+ // Try all versions of this package.
+ for(VerIterator V = d.TargetPkg().VersionList();
+ !V.end(); ++V)
+ {
+ if(_system->VS->CheckDep(V.VerStr(), d->CompareOp, d.TargetVer()))
+ {
+ MarkPackage(V.ParentPkg(), V,
+ follow_recommends, follow_suggests);
+ }
+ }
+ // Now try virtual packages
+ for(PrvIterator prv=d.TargetPkg().ProvidesList();
+ !prv.end(); ++prv)
+ {
+ if(_system->VS->CheckDep(prv.ProvideVersion(), d->CompareOp,
+ d.TargetVer()))
+ {
+ MarkPackage(prv.OwnerPkg(), prv.OwnerVer(),
+ follow_recommends, follow_suggests);
+ }
+ }
+ }
+ }
+ }
+}
+
+bool pkgDepCache::Sweep()
+{
+ // do the sweep
+ for(PkgIterator p=PkgBegin(); !p.end(); ++p)
+ {
+ StateCache &state=PkgState[p->ID];
+
+ // skip required packages
+ if (!p.CurrentVer().end() &&
+ (p.CurrentVer()->Priority == pkgCache::State::Required))
+ continue;
+
+ // if it is not marked and it is installed, it's garbage
+ if(!state.Marked && (!p.CurrentVer().end() || state.Install()))
+ {
+ state.Garbage=true;
+ if(_config->FindB("Debug::pkgAutoRemove",false))
+ std::cout << "Garbage: " << p.Name() << std::endl;
+ }
+ }
+
+ return true;
+}
diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h
index 6d51920e9..7adf6fe7f 100644
--- a/apt-pkg/depcache.h
+++ b/apt-pkg/depcache.h
@@ -1,4 +1,4 @@
-// -*- mode: cpp; mode: fold -*-
+// -*- mode: c++; mode: fold -*-
// Description /*{{{*/
// $Id: depcache.h,v 1.14 2001/02/20 07:03:17 jgg Exp $
/* ######################################################################
@@ -38,16 +38,76 @@
#ifndef PKGLIB_DEPCACHE_H
#define PKGLIB_DEPCACHE_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/depcache.h"
-#endif
#include <apt-pkg/pkgcache.h>
#include <apt-pkg/progress.h>
+#include <regex.h>
+
+#include <vector>
+#include <memory>
+
class pkgDepCache : protected pkgCache::Namespace
{
public:
+
+ /** \brief An arbitrary predicate on packages. */
+ class InRootSetFunc
+ {
+ public:
+ virtual bool InRootSet(const pkgCache::PkgIterator &pkg) {return false;};
+ virtual ~InRootSetFunc() {};
+ };
+
+ private:
+ /** \brief Mark a single package and all its unmarked important
+ * dependencies during mark-and-sweep.
+ *
+ * Recursively invokes itself to mark all dependencies of the
+ * package.
+ *
+ * \param pkg The package to mark.
+ *
+ * \param ver The version of the package that is to be marked.
+ *
+ * \param follow_recommends If \b true, recommendations of the
+ * package will be recursively marked.
+ *
+ * \param follow_suggests If \b true, suggestions of the package
+ * will be recursively marked.
+ */
+ void MarkPackage(const pkgCache::PkgIterator &pkg,
+ const pkgCache::VerIterator &ver,
+ bool follow_recommends,
+ bool follow_suggests);
+
+ /** \brief Update the Marked field of all packages.
+ *
+ * Each package's StateCache::Marked field will be set to \b true
+ * if and only if it can be reached from the root set. By
+ * default, the root set consists of the set of manually installed
+ * or essential packages, but it can be extended using the
+ * parameter #rootFunc.
+ *
+ * \param rootFunc A callback that can be used to add extra
+ * packages to the root set.
+ *
+ * \return \b false if an error occured.
+ */
+ bool MarkRequired(InRootSetFunc &rootFunc);
+
+ /** \brief Set the StateCache::Garbage flag on all packages that
+ * should be removed.
+ *
+ * Packages that were not marked by the last call to #MarkRequired
+ * are tested to see whether they are actually garbage. If so,
+ * they are marked as such.
+ *
+ * \return \b false if an error occured.
+ */
+ bool Sweep();
+
+ public:
// These flags are used in DepState
enum DepFlags {DepNow = (1 << 0),DepInstall = (1 << 1),DepCVer = (1 << 2),
@@ -63,6 +123,84 @@ class pkgDepCache : protected pkgCache::Namespace
enum VersionTypes {NowVersion, InstallVersion, CandidateVersion};
enum ModeList {ModeDelete = 0, ModeKeep = 1, ModeInstall = 2};
+
+ /** \brief Represents an active action group.
+ *
+ * An action group is a group of actions that are currently being
+ * performed. While an active group is active, certain routine
+ * clean-up actions that would normally be performed after every
+ * cache operation are delayed until the action group is
+ * completed. This is necessary primarily to avoid inefficiencies
+ * when modifying a large number of packages at once.
+ *
+ * This class represents an active action group. Creating an
+ * instance will create an action group; destroying one will
+ * destroy the corresponding action group.
+ *
+ * The following operations are suppressed by this class:
+ *
+ * - Keeping the Marked and Garbage flags up to date.
+ *
+ * \note This can be used in the future to easily accumulate
+ * atomic actions for undo or to display "what apt did anyway";
+ * e.g., change the counter of how many action groups are active
+ * to a std::set of pointers to them and use those to store
+ * information about what happened in a group in the group.
+ */
+ class ActionGroup
+ {
+ pkgDepCache &cache;
+
+ bool released;
+
+ /** Action groups are noncopyable. */
+ ActionGroup(const ActionGroup &other);
+ public:
+ /** \brief Create a new ActionGroup.
+ *
+ * \param cache The cache that this ActionGroup should
+ * manipulate.
+ *
+ * As long as this object exists, no automatic cleanup
+ * operations will be undertaken.
+ */
+ ActionGroup(pkgDepCache &cache);
+
+ /** \brief Clean up the action group before it is destroyed.
+ *
+ * If it is destroyed later, no second cleanup wil be run.
+ */
+ void release();
+
+ /** \brief Destroy the action group.
+ *
+ * If this is the last action group, the automatic cache
+ * cleanup operations will be undertaken.
+ */
+ ~ActionGroup();
+ };
+
+ /** \brief Returns \b true for packages matching a regular
+ * expression in APT::NeverAutoRemove.
+ */
+ class DefaultRootSetFunc : public InRootSetFunc
+ {
+ std::vector<regex_t *> rootSetRegexp;
+ bool constructedSuccessfully;
+
+ public:
+ DefaultRootSetFunc();
+ ~DefaultRootSetFunc();
+
+ /** \return \b true if the class initialized successfully, \b
+ * false otherwise. Used to avoid throwing an exception, since
+ * APT classes generally don't.
+ */
+ bool wasConstructedSuccessfully() const { return constructedSuccessfully; }
+
+ bool InRootSet(const pkgCache::PkgIterator &pkg);
+ };
+
struct StateCache
{
// Epoch stripped text versions of the two version fields
@@ -79,6 +217,17 @@ class pkgDepCache : protected pkgCache::Namespace
unsigned short Flags;
unsigned short iFlags; // Internal flags
+ /** \brief \b true if this package can be reached from the root set. */
+ bool Marked;
+
+ /** \brief \b true if this package is unused and should be removed.
+ *
+ * This differs from !#Marked, because it is possible that some
+ * unreachable packages will be protected from becoming
+ * garbage.
+ */
+ bool Garbage;
+
// Various tree indicators
signed char Status; // -1,0,1,2
unsigned char Mode; // ModeList
@@ -97,7 +246,9 @@ class pkgDepCache : protected pkgCache::Namespace
inline bool Downgrade() const {return Status < 0 && Mode == ModeInstall;};
inline bool Held() const {return Status != 0 && Keep();};
inline bool NowBroken() const {return (DepState & DepNowMin) != DepNowMin;};
+ inline bool NowPolicyBroken() const {return (DepState & DepNowPolicy) != DepNowPolicy;};
inline bool InstBroken() const {return (DepState & DepInstMin) != DepInstMin;};
+ inline bool InstPolicyBroken() const {return (DepState & DepInstPolicy) != DepInstPolicy;};
inline bool Install() const {return Mode == ModeInstall;};
inline VerIterator InstVerIter(pkgCache &Cache)
{return VerIterator(Cache,InstallVer);};
@@ -119,6 +270,14 @@ class pkgDepCache : protected pkgCache::Namespace
virtual ~Policy() {};
};
+
+ private:
+ /** The number of open "action groups"; certain post-action
+ * operations are suppressed if this number is > 0.
+ */
+ int group_level;
+
+ friend class ActionGroup;
protected:
@@ -133,6 +292,7 @@ class pkgDepCache : protected pkgCache::Namespace
unsigned long iDelCount;
unsigned long iKeepCount;
unsigned long iBrokenCount;
+ unsigned long iPolicyBrokenCount;
unsigned long iBadCount;
Policy *delLocalPolicy; // For memory clean up..
@@ -182,16 +342,69 @@ class pkgDepCache : protected pkgCache::Namespace
inline StateCache &operator [](PkgIterator const &I) {return PkgState[I->ID];};
inline unsigned char &operator [](DepIterator const &I) {return DepState[I->ID];};
- // Manipulators
- void MarkKeep(PkgIterator const &Pkg,bool Soft = false);
+ /** \return A function identifying packages in the root set other
+ * than manually installed packages and essential packages, or \b
+ * NULL if an error occurs.
+ *
+ * \todo Is this the best place for this function? Perhaps the
+ * settings for mark-and-sweep should be stored in a single
+ * external class?
+ */
+ virtual InRootSetFunc *GetRootSetFunc();
+
+ /** \return \b true if the garbage collector should follow recommendations.
+ */
+ virtual bool MarkFollowsRecommends();
+
+ /** \return \b true if the garbage collector should follow suggestions.
+ */
+ virtual bool MarkFollowsSuggests();
+
+ /** \brief Update the Marked and Garbage fields of all packages.
+ *
+ * This routine is implicitly invoked after all state manipulators
+ * and when an ActionGroup is destroyed. It invokes #MarkRequired
+ * and #Sweep to do its dirty work.
+ *
+ * \param rootFunc A predicate that returns \b true for packages
+ * that should be added to the root set.
+ */
+ bool MarkAndSweep(InRootSetFunc &rootFunc)
+ {
+ return MarkRequired(rootFunc) && Sweep();
+ }
+
+ bool MarkAndSweep()
+ {
+ std::auto_ptr<InRootSetFunc> f(GetRootSetFunc());
+ if(f.get() != NULL)
+ return MarkAndSweep(*f.get());
+ else
+ return false;
+ }
+
+ /** \name State Manipulators
+ */
+ // @{
+ void MarkKeep(PkgIterator const &Pkg, bool Soft = false,
+ bool FromUser = true);
void MarkDelete(PkgIterator const &Pkg,bool Purge = false);
void MarkInstall(PkgIterator const &Pkg,bool AutoInst = true,
- unsigned long Depth = 0);
+ unsigned long Depth = 0, bool FromUser = true,
+ bool ForceImportantDeps = false);
void SetReInstall(PkgIterator const &Pkg,bool To);
void SetCandidateVersion(VerIterator TargetVer);
+
+ /** Set the "is automatically installed" flag of Pkg. */
+ void MarkAuto(const PkgIterator &Pkg, bool Auto);
+ // @}
// This is for debuging
void Update(OpProgress *Prog = 0);
+
+ // read persistent states
+ bool readStateFile(OpProgress *prog);
+ bool writeStateFile(OpProgress *prog, bool InstalledOnly=false);
// Size queries
inline double UsrSize() {return iUsrSize;};
@@ -200,6 +413,7 @@ class pkgDepCache : protected pkgCache::Namespace
inline unsigned long KeepCount() {return iKeepCount;};
inline unsigned long InstCount() {return iInstCount;};
inline unsigned long BrokenCount() {return iBrokenCount;};
+ inline unsigned long PolicyBrokenCount() {return iPolicyBrokenCount;};
inline unsigned long BadCount() {return iBadCount;};
bool Init(OpProgress *Prog);
diff --git a/apt-pkg/indexcopy.cc b/apt-pkg/indexcopy.cc
index 1f65062f7..b30777d8d 100644
--- a/apt-pkg/indexcopy.cc
+++ b/apt-pkg/indexcopy.cc
@@ -32,6 +32,8 @@
using namespace std;
+
+
// IndexCopy::CopyPackages - Copy the package files from the CD /*{{{*/
// ---------------------------------------------------------------------
/* */
@@ -512,10 +514,10 @@ bool SourceCopy::RewriteEntry(FILE *Target,string File)
fputc('\n',Target);
return true;
}
-
-
/*}}}*/
-
+// SigVerify::Verify - Verify a files md5sum against its metaindex /*{{{*/
+// ---------------------------------------------------------------------
+/* */
bool SigVerify::Verify(string prefix, string file, indexRecords *MetaIndex)
{
const indexRecords::checkSum *Record = MetaIndex->Lookup(file);
@@ -526,23 +528,16 @@ bool SigVerify::Verify(string prefix, string file, indexRecords *MetaIndex)
return false;
}
- MD5Summation sum;
- FileFd Fd(prefix+file, FileFd::ReadOnly);
- sum.AddFD(Fd.Fd(), Fd.Size());
- Fd.Close();
- string MD5 = (string)sum.Result();
-
- if (Record->MD5Hash != MD5)
+ if (!Record->Hash.VerifyFile(prefix+file))
{
- _error->Warning("MD5 mismatch for: %s",file.c_str());
+ _error->Warning("Hash mismatch for: %s",file.c_str());
return false;
}
if(_config->FindB("Debug::aptcdrom",false))
{
cout << "File: " << prefix+file << endl;
- cout << "Expected MD5sum: " << Record->MD5Hash << endl;
- cout << "got: " << MD5 << endl << endl;
+ cout << "Expected Hash " << Record->Hash.toStr() << endl;
}
return true;
@@ -670,3 +665,178 @@ bool SigVerify::CopyAndVerify(string CDROM,string Name,vector<string> &SigList,
return true;
}
+
+
+bool TranslationsCopy::CopyTranslations(string CDROM,string Name,vector<string> &List,
+ pkgCdromStatus *log)
+{
+ OpProgress *Progress = NULL;
+ if (List.size() == 0)
+ return true;
+
+ if(log)
+ Progress = log->GetOpProgress();
+
+ bool Debug = _config->FindB("Debug::aptcdrom",false);
+
+ // Prepare the progress indicator
+ unsigned long TotalSize = 0;
+ for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
+ {
+ struct stat Buf;
+ if (stat(string(*I).c_str(),&Buf) != 0 &&
+ stat(string(*I + ".gz").c_str(),&Buf) != 0)
+ return _error->Errno("stat","Stat failed for %s",
+ string(*I).c_str());
+ TotalSize += Buf.st_size;
+ }
+
+ unsigned long CurrentSize = 0;
+ unsigned int NotFound = 0;
+ unsigned int WrongSize = 0;
+ unsigned int Packages = 0;
+ for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
+ {
+ string OrigPath = string(*I,CDROM.length());
+ unsigned long FileSize = 0;
+
+ // Open the package file
+ FileFd Pkg;
+ if (FileExists(*I) == true)
+ {
+ Pkg.Open(*I,FileFd::ReadOnly);
+ FileSize = Pkg.Size();
+ }
+ else
+ {
+ FileFd From(*I + ".gz",FileFd::ReadOnly);
+ if (_error->PendingError() == true)
+ return false;
+ FileSize = From.Size();
+
+ // Get a temp file
+ FILE *tmp = tmpfile();
+ if (tmp == 0)
+ return _error->Errno("tmpfile","Unable to create a tmp file");
+ Pkg.Fd(dup(fileno(tmp)));
+ fclose(tmp);
+
+ // Fork gzip
+ pid_t Process = fork();
+ if (Process < 0)
+ return _error->Errno("fork","Couldn't fork gzip");
+
+ // The child
+ if (Process == 0)
+ {
+ dup2(From.Fd(),STDIN_FILENO);
+ dup2(Pkg.Fd(),STDOUT_FILENO);
+ SetCloseExec(STDIN_FILENO,false);
+ SetCloseExec(STDOUT_FILENO,false);
+
+ const char *Args[3];
+ string Tmp = _config->Find("Dir::bin::gzip","gzip");
+ Args[0] = Tmp.c_str();
+ Args[1] = "-d";
+ Args[2] = 0;
+ execvp(Args[0],(char **)Args);
+ exit(100);
+ }
+
+ // Wait for gzip to finish
+ if (ExecWait(Process,_config->Find("Dir::bin::gzip","gzip").c_str(),false) == false)
+ return _error->Error("gzip failed, perhaps the disk is full.");
+
+ Pkg.Seek(0);
+ }
+ pkgTagFile Parser(&Pkg);
+ if (_error->PendingError() == true)
+ return false;
+
+ // Open the output file
+ char S[400];
+ snprintf(S,sizeof(S),"cdrom:[%s]/%s",Name.c_str(),
+ (*I).c_str() + CDROM.length());
+ string TargetF = _config->FindDir("Dir::State::lists") + "partial/";
+ TargetF += URItoFileName(S);
+ if (_config->FindB("APT::CDROM::NoAct",false) == true)
+ TargetF = "/dev/null";
+ FileFd Target(TargetF,FileFd::WriteEmpty);
+ FILE *TargetFl = fdopen(dup(Target.Fd()),"w");
+ if (_error->PendingError() == true)
+ return false;
+ if (TargetFl == 0)
+ return _error->Errno("fdopen","Failed to reopen fd");
+
+ // Setup the progress meter
+ if(Progress)
+ Progress->OverallProgress(CurrentSize,TotalSize,FileSize,
+ string("Reading Translation Indexes"));
+
+ // Parse
+ if(Progress)
+ Progress->SubProgress(Pkg.Size());
+ pkgTagSection Section;
+ this->Section = &Section;
+ string Prefix;
+ unsigned long Hits = 0;
+ unsigned long Chop = 0;
+ while (Parser.Step(Section) == true)
+ {
+ if(Progress)
+ Progress->Progress(Parser.Offset());
+
+ const char *Start;
+ const char *Stop;
+ Section.GetSection(Start,Stop);
+ fwrite(Start,Stop-Start, 1, TargetFl);
+ fputc('\n',TargetFl);
+
+ Packages++;
+ Hits++;
+ }
+ fclose(TargetFl);
+
+ if (Debug == true)
+ cout << " Processed by using Prefix '" << Prefix << "' and chop " << Chop << endl;
+
+ if (_config->FindB("APT::CDROM::NoAct",false) == false)
+ {
+ // Move out of the partial directory
+ Target.Close();
+ string FinalF = _config->FindDir("Dir::State::lists");
+ FinalF += URItoFileName(S);
+ if (rename(TargetF.c_str(),FinalF.c_str()) != 0)
+ return _error->Errno("rename","Failed to rename");
+ }
+
+
+ CurrentSize += FileSize;
+ }
+ if(Progress)
+ Progress->Done();
+
+ // Some stats
+ if(log) {
+ stringstream msg;
+ if(NotFound == 0 && WrongSize == 0)
+ ioprintf(msg, _("Wrote %i records.\n"), Packages);
+ else if (NotFound != 0 && WrongSize == 0)
+ ioprintf(msg, _("Wrote %i records with %i missing files.\n"),
+ Packages, NotFound);
+ else if (NotFound == 0 && WrongSize != 0)
+ ioprintf(msg, _("Wrote %i records with %i mismatched files\n"),
+ Packages, WrongSize);
+ if (NotFound != 0 && WrongSize != 0)
+ ioprintf(msg, _("Wrote %i records with %i missing files and %i mismatched files\n"), Packages, NotFound, WrongSize);
+ }
+
+ if (Packages == 0)
+ _error->Warning("No valid records were found.");
+
+ if (NotFound + WrongSize > 10)
+ _error->Warning("Alot of entries were discarded, something may be wrong.\n");
+
+
+ return true;
+}
diff --git a/apt-pkg/indexcopy.h b/apt-pkg/indexcopy.h
index 4dcb2b46d..7778ae595 100644
--- a/apt-pkg/indexcopy.h
+++ b/apt-pkg/indexcopy.h
@@ -70,6 +70,17 @@ class SourceCopy : public IndexCopy
public:
};
+class TranslationsCopy
+{
+ protected:
+ pkgTagSection *Section;
+
+ public:
+ bool CopyTranslations(string CDROM,string Name,vector<string> &List,
+ pkgCdromStatus *log);
+};
+
+
class SigVerify
{
bool Verify(string prefix,string file, indexRecords *records);
@@ -81,4 +92,6 @@ class SigVerify
vector<string> PkgList,vector<string> SrcList);
};
+
+
#endif
diff --git a/apt-pkg/indexfile.cc b/apt-pkg/indexfile.cc
index 49665161d..b38596143 100644
--- a/apt-pkg/indexfile.cc
+++ b/apt-pkg/indexfile.cc
@@ -8,12 +8,12 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/indexfile.h"
-#endif
-
+#include <apt-pkg/configuration.h>
#include <apt-pkg/indexfile.h>
#include <apt-pkg/error.h>
+
+#include <clocale>
+#include <cstring>
/*}}}*/
// Global list of Item supported
@@ -67,3 +67,63 @@ string pkgIndexFile::SourceInfo(pkgSrcRecords::Parser const &Record,
return string();
}
/*}}}*/
+// IndexFile::TranslationsAvailable - Check if will use Translation /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool pkgIndexFile::TranslationsAvailable()
+{
+ const string Translation = _config->Find("APT::Acquire::Translation");
+
+ if (Translation.compare("none") != 0)
+ return CheckLanguageCode(LanguageCode().c_str());
+ else
+ return false;
+}
+ /*}}}*/
+// IndexFile::CheckLanguageCode - Check the Language Code /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+/* common cases: de_DE, de_DE@euro, de_DE.UTF-8, de_DE.UTF-8@euro,
+ de_DE.ISO8859-1, tig_ER
+ more in /etc/gdm/locale.conf
+*/
+
+bool pkgIndexFile::CheckLanguageCode(const char *Lang)
+{
+ if (strlen(Lang) == 2 || (strlen(Lang) == 5 && Lang[2] == '_'))
+ return true;
+
+ if (strcmp(Lang,"C") != 0)
+ _error->Warning("Wrong language code %s", Lang);
+
+ return false;
+}
+ /*}}}*/
+// IndexFile::LanguageCode - Return the Language Code /*{{{*/
+// ---------------------------------------------------------------------
+/* return the language code */
+string pkgIndexFile::LanguageCode()
+{
+ const string Translation = _config->Find("APT::Acquire::Translation");
+
+ if (Translation.compare("environment") == 0)
+ {
+ string lang = std::setlocale(LC_MESSAGES,NULL);
+
+ // we have a mapping of the language codes that contains all the language
+ // codes that need the country code as well
+ // (like pt_BR, pt_PT, sv_SE, zh_*, en_*)
+ const char *need_full_langcode[] = { "pt","sv","zh","en", NULL };
+ for(const char **s = need_full_langcode;*s != NULL; s++)
+ if(lang.find(*s) == 0)
+ return lang.substr(0,5);
+
+ if(lang.size() > 2)
+ return lang.substr(0,2);
+ else
+ return lang;
+ }
+ else
+ return Translation;
+}
+ /*}}}*/
diff --git a/apt-pkg/indexfile.h b/apt-pkg/indexfile.h
index 61049f4bd..3cc501629 100644
--- a/apt-pkg/indexfile.h
+++ b/apt-pkg/indexfile.h
@@ -5,10 +5,11 @@
Index File - Abstraction for an index of archive/source file.
- There are 3 primary sorts of index files, all represented by this
+ There are 4 primary sorts of index files, all represented by this
class:
Binary index files
+ Binary translation files
Bianry index files decribing the local system
Source index files
@@ -21,9 +22,6 @@
#ifndef PKGLIB_INDEXFILE_H
#define PKGLIB_INDEXFILE_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/indexfile.h"
-#endif
#include <string>
#include <apt-pkg/pkgcache.h>
@@ -80,6 +78,10 @@ class pkgIndexFile
virtual bool MergeFileProvides(pkgCacheGenerator &/*Gen*/,OpProgress &/*Prog*/) const {return true;};
virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const;
+ static bool TranslationsAvailable();
+ static bool CheckLanguageCode(const char *Lang);
+ static string LanguageCode();
+
bool IsTrusted() const { return Trusted; };
pkgIndexFile(bool Trusted): Trusted(Trusted) {};
diff --git a/apt-pkg/indexrecords.cc b/apt-pkg/indexrecords.cc
index 06ed7921c..502f454a8 100644
--- a/apt-pkg/indexrecords.cc
+++ b/apt-pkg/indexrecords.cc
@@ -3,9 +3,6 @@
// $Id: indexrecords.cc,v 1.1.2.4 2003/12/30 02:11:43 mdz Exp $
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/indexrecords.h"
-#endif
#include <apt-pkg/indexrecords.h>
#include <apt-pkg/tagfile.h>
#include <apt-pkg/error.h>
@@ -53,32 +50,38 @@ bool indexRecords::Load(const string Filename)
const char *Start, *End;
Section.Get (Start, End, 0);
+
Suite = Section.FindS("Suite");
Dist = Section.FindS("Codename");
-// if (Dist.empty())
-// {
-// ErrorText = _(("No Codename entry in Release file " + Filename).c_str());
-// return false;
-// }
- if (!Section.Find("MD5Sum", Start, End))
+
+ int i;
+ for (i=0;HashString::SupportedHashes()[i] != NULL; i++)
{
- ErrorText = _(("No MD5Sum entry in Release file " + Filename).c_str());
- return false;
+ if (!Section.Find(HashString::SupportedHashes()[i], Start, End))
+ continue;
+
+ string Name;
+ string Hash;
+ size_t Size;
+ while (Start < End)
+ {
+ if (!parseSumData(Start, End, Name, Hash, Size))
+ return false;
+ indexRecords::checkSum *Sum = new indexRecords::checkSum;
+ Sum->MetaKeyFilename = Name;
+ Sum->Hash = HashString(HashString::SupportedHashes()[i],Hash);
+ Sum->Size = Size;
+ Entries[Name] = Sum;
+ }
+ break;
}
- string Name;
- string MD5Hash;
- size_t Size;
- while (Start < End)
+
+ if(HashString::SupportedHashes()[i] == NULL)
{
- if (!parseSumData(Start, End, Name, MD5Hash, Size))
- return false;
- indexRecords::checkSum *Sum = new indexRecords::checkSum;
- Sum->MetaKeyFilename = Name;
- Sum->MD5Hash = MD5Hash;
- Sum->Size = Size;
- Entries[Name] = Sum;
- }
-
+ ErrorText = _(("No Hash entry in Release file " + Filename).c_str());
+ return false;
+ }
+
string Strdate = Section.FindS("Date"); // FIXME: verify this somehow?
return true;
}
diff --git a/apt-pkg/indexrecords.h b/apt-pkg/indexrecords.h
index 414faceaa..468d2bd0f 100644
--- a/apt-pkg/indexrecords.h
+++ b/apt-pkg/indexrecords.h
@@ -5,11 +5,10 @@
#ifndef PKGLIB_INDEXRECORDS_H
#define PKGLIB_INDEXRECORDS_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/indexrecords.h"
-#endif
+
#include <apt-pkg/pkgcache.h>
#include <apt-pkg/fileutl.h>
+#include <apt-pkg/hashes.h>
#include <map>
#include <vector>
@@ -47,7 +46,7 @@ class indexRecords
struct indexRecords::checkSum
{
string MetaKeyFilename;
- string MD5Hash;
+ HashString Hash;
size_t Size;
};
diff --git a/apt-pkg/init.cc b/apt-pkg/init.cc
index b47378d4a..338bef66c 100644
--- a/apt-pkg/init.cc
+++ b/apt-pkg/init.cc
@@ -14,6 +14,7 @@
#include <apti18n.h>
#include <config.h>
+#include <cstdlib>
#include <sys/stat.h>
/*}}}*/
@@ -23,8 +24,6 @@ const char *pkgVersion = VERSION;
const char *pkgLibVersion = Stringfy(APT_PKG_MAJOR) "."
Stringfy(APT_PKG_MINOR) "."
Stringfy(APT_PKG_RELEASE);
-const char *pkgCPU = COMMON_CPU;
-const char *pkgOS = COMMON_OS;
// pkgInitConfig - Initialize the configuration class /*{{{*/
// ---------------------------------------------------------------------
@@ -34,12 +33,10 @@ const char *pkgOS = COMMON_OS;
bool pkgInitConfig(Configuration &Cnf)
{
// General APT things
- if (strcmp(COMMON_OS,"linux") == 0 ||
- strcmp(COMMON_OS,"unknown") == 0)
- Cnf.Set("APT::Architecture",COMMON_CPU);
- else
- Cnf.Set("APT::Architecture",COMMON_OS "-" COMMON_CPU);
+ Cnf.Set("APT::Architecture", COMMON_ARCH);
Cnf.Set("APT::Build-Essential::", "build-essential");
+ Cnf.Set("APT::Install-Recommends", true);
+ Cnf.Set("APT::Install-Suggests", false);
Cnf.Set("Dir","/");
// State
@@ -71,7 +68,14 @@ bool pkgInitConfig(Configuration &Cnf)
Cnf.Set("Dir::Etc::parts","apt.conf.d");
Cnf.Set("Dir::Etc::preferences","preferences");
Cnf.Set("Dir::Bin::methods","/usr/lib/apt/methods");
-
+
+ // State
+ Cnf.Set("Dir::Log","var/log/apt");
+ Cnf.Set("Dir::Log::Terminal","term.log");
+
+ // Translation
+ Cnf.Set("APT::Acquire::Translation", "environment");
+
bool Res = true;
// Read an alternate config file
@@ -102,7 +106,7 @@ bool pkgInitConfig(Configuration &Cnf)
bindtextdomain(textdomain(0),Cnf.FindDir("Dir::Locale").c_str());
}
#endif
-
+
return true;
}
/*}}}*/
diff --git a/apt-pkg/init.h b/apt-pkg/init.h
index b584b2cce..6d8693be9 100644
--- a/apt-pkg/init.h
+++ b/apt-pkg/init.h
@@ -17,14 +17,12 @@
#include <apt-pkg/pkgsystem.h>
// See the makefile
-#define APT_PKG_MAJOR 3
-#define APT_PKG_MINOR 12
+#define APT_PKG_MAJOR 4
+#define APT_PKG_MINOR 6
#define APT_PKG_RELEASE 0
extern const char *pkgVersion;
extern const char *pkgLibVersion;
-extern const char *pkgOS;
-extern const char *pkgCPU;
bool pkgInitConfig(Configuration &Cnf);
bool pkgInitSystem(Configuration &Cnf,pkgSystem *&Sys);
diff --git a/apt-pkg/makefile b/apt-pkg/makefile
index ab0ff8005..1b78c94f6 100644
--- a/apt-pkg/makefile
+++ b/apt-pkg/makefile
@@ -13,19 +13,19 @@ include ../buildlib/defaults.mak
# methods/makefile - FIXME
LIBRARY=apt-pkg
LIBEXT=$(GLIBC_VER)$(LIBSTDCPP_VER)
-MAJOR=3.12
+MAJOR=4.6
MINOR=0
-SLIBS=$(PTHREADLIB) $(INTLLIBS)
+SLIBS=$(PTHREADLIB) $(INTLLIBS) -lutil
APT_DOMAIN:=libapt-pkg$(MAJOR)
# Source code for the contributed non-core things
SOURCE = contrib/mmap.cc contrib/error.cc contrib/strutl.cc \
contrib/configuration.cc contrib/progress.cc contrib/cmndline.cc \
- contrib/md5.cc contrib/sha1.cc contrib/hashes.cc \
+ contrib/md5.cc contrib/sha1.cc contrib/sha256.cc contrib/hashes.cc \
contrib/cdromutl.cc contrib/crc-16.cc \
contrib/fileutl.cc
HEADERS = mmap.h error.h configuration.h fileutl.h cmndline.h \
- md5.h crc-16.h cdromutl.h strutl.h sptr.h sha1.h hashes.h
+ md5.h crc-16.h cdromutl.h strutl.h sptr.h sha1.h sha256.h hashes.h
# Source code for the core main library
SOURCE+= pkgcache.cc version.cc depcache.cc \
diff --git a/apt-pkg/metaindex.h b/apt-pkg/metaindex.h
index 8ebf23541..2b87d7da9 100644
--- a/apt-pkg/metaindex.h
+++ b/apt-pkg/metaindex.h
@@ -1,9 +1,6 @@
#ifndef PKGLIB_METAINDEX_H
#define PKGLIB_METAINDEX_H
-/* #ifdef __GNUG__ */
-/* #pragma interface "apt-pkg/metaindex.h" */
-/* #endif */
#include <string>
#include <apt-pkg/pkgcache.h>
diff --git a/apt-pkg/orderlist.cc b/apt-pkg/orderlist.cc
index 8d3a97983..616714e29 100644
--- a/apt-pkg/orderlist.cc
+++ b/apt-pkg/orderlist.cc
@@ -63,9 +63,6 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/orderlist.h"
-#endif
#include <apt-pkg/orderlist.h>
#include <apt-pkg/depcache.h>
#include <apt-pkg/error.h>
@@ -491,11 +488,13 @@ bool pkgOrderList::VisitProvides(DepIterator D,bool Critical)
continue;
if (D->Type != pkgCache::Dep::Conflicts &&
+ D->Type != pkgCache::Dep::DpkgBreaks &&
D->Type != pkgCache::Dep::Obsoletes &&
Cache[Pkg].InstallVer != *I)
continue;
if ((D->Type == pkgCache::Dep::Conflicts ||
+ D->Type == pkgCache::Dep::DpkgBreaks ||
D->Type == pkgCache::Dep::Obsoletes) &&
(Version *)Pkg.CurrentVer() != *I)
continue;
@@ -630,6 +629,7 @@ bool pkgOrderList::DepUnPackCrit(DepIterator D)
/* Forward critical dependencies MUST be correct before the
package can be unpacked. */
if (D->Type != pkgCache::Dep::Conflicts &&
+ D->Type != pkgCache::Dep::DpkgBreaks &&
D->Type != pkgCache::Dep::Obsoletes &&
D->Type != pkgCache::Dep::PreDepends)
continue;
@@ -668,7 +668,7 @@ bool pkgOrderList::DepUnPackCrit(DepIterator D)
}
return true;
}
- /*}}}*/
+
// OrderList::DepUnPackPreD - Critical UnPacking ordering with depends /*{{{*/
// ---------------------------------------------------------------------
/* Critical PreDepends (also configure immediate and essential) strives to
@@ -803,9 +803,20 @@ bool pkgOrderList::DepUnPackDep(DepIterator D)
return false;
}
else
+ {
if (D->Type == pkgCache::Dep::Depends)
if (VisitProvides(D,false) == false)
return false;
+
+ if (D->Type == pkgCache::Dep::DpkgBreaks)
+ {
+ if (CheckDep(D) == true)
+ continue;
+
+ if (VisitNode(D.TargetPkg()) == false)
+ return false;
+ }
+ }
}
return true;
}
@@ -953,6 +964,7 @@ bool pkgOrderList::CheckDep(DepIterator D)
/* Conflicts requires that all versions are not present, depends
just needs one */
if (D->Type != pkgCache::Dep::Conflicts &&
+ D->Type != pkgCache::Dep::DpkgBreaks &&
D->Type != pkgCache::Dep::Obsoletes)
{
/* Try to find something that does not have the after flag set
diff --git a/apt-pkg/orderlist.h b/apt-pkg/orderlist.h
index d13301bcf..bbceb3879 100644
--- a/apt-pkg/orderlist.h
+++ b/apt-pkg/orderlist.h
@@ -16,9 +16,6 @@
#ifndef PKGLIB_ORDERLIST_H
#define PKGLIB_ORDERLIST_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/orderlist.h"
-#endif
#include <apt-pkg/pkgcache.h>
diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc
index 4b3dd8be2..c391a6036 100644
--- a/apt-pkg/packagemanager.cc
+++ b/apt-pkg/packagemanager.cc
@@ -13,10 +13,6 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/packagemanager.h"
-#endif
-
#include <apt-pkg/packagemanager.h>
#include <apt-pkg/orderlist.h>
#include <apt-pkg/depcache.h>
@@ -29,7 +25,7 @@
#include <apti18n.h>
#include <iostream>
- /*}}}*/
+#include <fcntl.h>
using namespace std;
@@ -95,9 +91,10 @@ bool pkgPackageManager::GetArchives(pkgAcquire *Owner,pkgSourceList *Sources,
be downloaded. */
bool pkgPackageManager::FixMissing()
{
+ pkgDepCache::ActionGroup group(Cache);
pkgProblemResolver Resolve(&Cache);
List->SetFileList(FileNames);
-
+
bool Bad = false;
for (PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
{
@@ -106,7 +103,7 @@ bool pkgPackageManager::FixMissing()
// Okay, this file is missing and we need it. Mark it for keep
Bad = true;
- Cache.MarkKeep(I);
+ Cache.MarkKeep(I, false, false);
}
// We have to empty the list otherwise it will not have the new changes
@@ -121,6 +118,41 @@ bool pkgPackageManager::FixMissing()
}
/*}}}*/
+// PM::ImmediateAdd - Add the immediate flag recursivly /*{{{*/
+// ---------------------------------------------------------------------
+/* This adds the immediate flag to the pkg and recursively to the
+ dependendies
+ */
+void pkgPackageManager::ImmediateAdd(PkgIterator I, bool UseInstallVer)
+{
+ DepIterator D;
+
+ if(UseInstallVer)
+ {
+ if(Cache[I].InstallVer == 0)
+ return;
+ D = Cache[I].InstVerIter(Cache).DependsList();
+ } else {
+ if (I->CurrentVer == 0)
+ return;
+ D = I.CurrentVer().DependsList();
+ }
+
+ for ( /* nothing */ ; D.end() == false; D++)
+ if (D->Type == pkgCache::Dep::Depends || D->Type == pkgCache::Dep::PreDepends)
+ {
+ if(!List->IsFlag(D.TargetPkg(), pkgOrderList::Immediate))
+ {
+ if(Debug)
+ clog << "ImmediateAdd(): Adding Immediate flag to " << I.Name() << endl;
+ List->Flag(D.TargetPkg(),pkgOrderList::Immediate);
+ ImmediateAdd(D.TargetPkg(), UseInstallVer);
+ }
+ }
+ return;
+}
+ /*}}}*/
+
// PM::CreateOrderList - Create the ordering class /*{{{*/
// ---------------------------------------------------------------------
/* This populates the ordering list with all the packages that are
@@ -147,21 +179,15 @@ bool pkgPackageManager::CreateOrderList()
(I->Flags & pkgCache::Flag::Important) == pkgCache::Flag::Important) &&
NoImmConfigure == false)
{
+ if(Debug)
+ clog << "CreateOrderList(): Adding Immediate flag for " << I.Name() << endl;
List->Flag(I,pkgOrderList::Immediate);
-
- // Look for other packages to make immediate configurea
- if (Cache[I].InstallVer != 0)
- for (DepIterator D = Cache[I].InstVerIter(Cache).DependsList();
- D.end() == false; D++)
- if (D->Type == pkgCache::Dep::Depends || D->Type == pkgCache::Dep::PreDepends)
- List->Flag(D.TargetPkg(),pkgOrderList::Immediate);
+
+ // Look for other install packages to make immediate configurea
+ ImmediateAdd(I, true);
// And again with the current version.
- if (I->CurrentVer != 0)
- for (DepIterator D = I.CurrentVer().DependsList();
- D.end() == false; D++)
- if (D->Type == pkgCache::Dep::Depends || D->Type == pkgCache::Dep::PreDepends)
- List->Flag(D.TargetPkg(),pkgOrderList::Immediate);
+ ImmediateAdd(I, false);
}
// Not interesting
@@ -627,18 +653,35 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall()
return Completed;
}
/*}}}*/
+// PM::DoInstallPostFork - Does install part that happens after the fork /*{{{*/
+// ---------------------------------------------------------------------
+pkgPackageManager::OrderResult
+pkgPackageManager::DoInstallPostFork(int statusFd)
+{
+ if(statusFd > 0)
+ // FIXME: use SetCloseExec here once it taught about throwing
+ // exceptions instead of doing _exit(100) on failure
+ fcntl(statusFd,F_SETFD,FD_CLOEXEC);
+ bool goResult = Go(statusFd);
+ if(goResult == false)
+ return Failed;
+
+ // if all was fine update the state file
+ if(Res == Completed) {
+ Cache.writeStateFile(NULL);
+ }
+ return Res;
+};
+
// PM::DoInstall - Does the installation /*{{{*/
// ---------------------------------------------------------------------
/* This uses the filenames in FileNames and the information in the
DepCache to perform the installation of packages.*/
-pkgPackageManager::OrderResult pkgPackageManager::DoInstall(int status_fd)
+pkgPackageManager::OrderResult pkgPackageManager::DoInstall(int statusFd)
{
- OrderResult Res = OrderInstall();
- if(Debug)
- std::clog << "OrderInstall() returned: " << Res << std::endl;
- if (Res != Failed)
- if (Go(status_fd) == false)
- return Failed;
- return Res;
+ if(DoInstallPreFork() == Failed)
+ return Failed;
+
+ return DoInstallPostFork(statusFd);
}
/*}}}*/
diff --git a/apt-pkg/packagemanager.h b/apt-pkg/packagemanager.h
index f64637d03..a1bfdc52d 100644
--- a/apt-pkg/packagemanager.h
+++ b/apt-pkg/packagemanager.h
@@ -23,12 +23,11 @@
#ifndef PKGLIB_PACKAGEMANAGER_H
#define PKGLIB_PACKAGEMANAGER_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/packagemanager.h"
-#endif
#include <string>
+#include <iostream>
#include <apt-pkg/pkgcache.h>
+#include <apt-pkg/depcache.h>
using std::string;
@@ -50,6 +49,7 @@ class pkgPackageManager : protected pkgCache::Namespace
bool Debug;
bool DepAdd(pkgOrderList &Order,PkgIterator P,int Depth = 0);
+ void ImmediateAdd(PkgIterator P, bool UseInstallVer);
virtual OrderResult OrderInstall();
bool CheckRConflicts(PkgIterator Pkg,DepIterator Dep,const char *Ver);
bool CreateOrderList();
@@ -70,13 +70,28 @@ class pkgPackageManager : protected pkgCache::Namespace
virtual bool Remove(PkgIterator /*Pkg*/,bool /*Purge*/=false) {return false;};
virtual bool Go(int statusFd=-1) {return true;};
virtual void Reset() {};
-
+
+ // the result of the operation
+ OrderResult Res;
+
public:
// Main action members
bool GetArchives(pkgAcquire *Owner,pkgSourceList *Sources,
pkgRecords *Recs);
- OrderResult DoInstall(int statusFd=-1);
+
+ // Do the installation
+ OrderResult DoInstall(int statusFd=-1);
+
+ // stuff that needs to be done before the fork() of a library that
+ // uses apt
+ OrderResult DoInstallPreFork() {
+ Res = OrderInstall();
+ return Res;
+ };
+
+ // stuff that needs to be done after the fork
+ OrderResult DoInstallPostFork(int statusFd=-1);
bool FixMissing();
pkgPackageManager(pkgDepCache *Cache);
diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc
index 9926befe9..133899a27 100644
--- a/apt-pkg/pkgcache.cc
+++ b/apt-pkg/pkgcache.cc
@@ -20,12 +20,8 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/pkgcache.h"
-#pragma implementation "apt-pkg/cacheiterators.h"
-#endif
-
#include <apt-pkg/pkgcache.h>
+#include <apt-pkg/indexfile.h>
#include <apt-pkg/version.h>
#include <apt-pkg/error.h>
#include <apt-pkg/strutl.h>
@@ -43,6 +39,7 @@
using std::string;
+
// Cache::Header::Header - Constructor /*{{{*/
// ---------------------------------------------------------------------
/* Simply initialize the header */
@@ -52,7 +49,7 @@ pkgCache::Header::Header()
/* Whenever the structures change the major version should be bumped,
whenever the generator changes the minor version should be bumped. */
- MajorVersion = 4;
+ MajorVersion = 7;
MinorVersion = 0;
Dirty = false;
@@ -60,17 +57,22 @@ pkgCache::Header::Header()
PackageSz = sizeof(pkgCache::Package);
PackageFileSz = sizeof(pkgCache::PackageFile);
VersionSz = sizeof(pkgCache::Version);
+ DescriptionSz = sizeof(pkgCache::Description);
DependencySz = sizeof(pkgCache::Dependency);
ProvidesSz = sizeof(pkgCache::Provides);
VerFileSz = sizeof(pkgCache::VerFile);
+ DescFileSz = sizeof(pkgCache::DescFile);
PackageCount = 0;
VersionCount = 0;
+ DescriptionCount = 0;
DependsCount = 0;
PackageFileCount = 0;
VerFileCount = 0;
+ DescFileCount = 0;
ProvidesCount = 0;
MaxVerFileSize = 0;
+ MaxDescFileSize = 0;
FileList = 0;
StringList = 0;
@@ -89,8 +91,10 @@ bool pkgCache::Header::CheckSizes(Header &Against) const
PackageSz == Against.PackageSz &&
PackageFileSz == Against.PackageFileSz &&
VersionSz == Against.VersionSz &&
+ DescriptionSz == Against.DescriptionSz &&
DependencySz == Against.DependencySz &&
VerFileSz == Against.VerFileSz &&
+ DescFileSz == Against.DescFileSz &&
ProvidesSz == Against.ProvidesSz)
return true;
return false;
@@ -115,8 +119,10 @@ bool pkgCache::ReMap()
HeaderP = (Header *)Map.Data();
PkgP = (Package *)Map.Data();
VerFileP = (VerFile *)Map.Data();
+ DescFileP = (DescFile *)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();
@@ -217,8 +223,8 @@ const char *pkgCache::DepType(unsigned char Type)
{
const char *Types[] = {"",_("Depends"),_("PreDepends"),_("Suggests"),
_("Recommends"),_("Conflicts"),_("Replaces"),
- _("Obsoletes")};
- if (Type < 8)
+ _("Obsoletes"),_("Breaks")};
+ if (Type < sizeof(Types)/sizeof(*Types))
return Types[Type];
return "";
}
@@ -235,11 +241,11 @@ const char *pkgCache::Priority(unsigned char Prio)
return 0;
}
/*}}}*/
-
// Bases for iterator classes /*{{{*/
void pkgCache::VerIterator::_dummy() {}
void pkgCache::DepIterator::_dummy() {}
void pkgCache::PrvIterator::_dummy() {}
+void pkgCache::DescIterator::_dummy() {}
/*}}}*/
// PkgIterator::operator ++ - Postfix incr /*{{{*/
// ---------------------------------------------------------------------
@@ -268,7 +274,9 @@ pkgCache::PkgIterator::OkState pkgCache::PkgIterator::State() const
return NeedsUnpack;
if (Pkg->CurrentState == pkgCache::State::UnPacked ||
- Pkg->CurrentState == pkgCache::State::HalfConfigured)
+ Pkg->CurrentState == pkgCache::State::HalfConfigured ||
+ Pkg->CurrentState == pkgCache::State::TriggersPending ||
+ Pkg->CurrentState == pkgCache::State::TriggersAwaited)
return NeedsConfigure;
if (Pkg->CurrentState == pkgCache::State::HalfInstalled ||
@@ -281,10 +289,11 @@ pkgCache::PkgIterator::OkState pkgCache::PkgIterator::State() const
// DepIterator::IsCritical - Returns true if the dep is important /*{{{*/
// ---------------------------------------------------------------------
/* Currently critical deps are defined as depends, predepends and
- conflicts. */
+ conflicts (including dpkg's Breaks fields). */
bool pkgCache::DepIterator::IsCritical()
{
if (Dep->Type == pkgCache::Dep::Conflicts ||
+ Dep->Type == pkgCache::Dep::DpkgBreaks ||
Dep->Type == pkgCache::Dep::Obsoletes ||
Dep->Type == pkgCache::Dep::Depends ||
Dep->Type == pkgCache::Dep::PreDepends)
@@ -370,6 +379,7 @@ pkgCache::Version **pkgCache::DepIterator::AllTargets()
continue;
if ((Dep->Type == pkgCache::Dep::Conflicts ||
+ Dep->Type == pkgCache::Dep::DpkgBreaks ||
Dep->Type == pkgCache::Dep::Obsoletes) &&
ParentPkg() == I.ParentPkg())
continue;
@@ -386,6 +396,7 @@ pkgCache::Version **pkgCache::DepIterator::AllTargets()
continue;
if ((Dep->Type == pkgCache::Dep::Conflicts ||
+ Dep->Type == pkgCache::Dep::DpkgBreaks ||
Dep->Type == pkgCache::Dep::Obsoletes) &&
ParentPkg() == I.OwnerPkg())
continue;
@@ -599,3 +610,20 @@ string pkgCache::PkgFileIterator::RelStr()
return Res;
}
/*}}}*/
+// VerIterator::TranslatedDescription - Return the a DescIter for locale/*{{{*/
+// ---------------------------------------------------------------------
+/* return a DescIter for the current locale or the default if none is
+ * found
+ */
+pkgCache::DescIterator pkgCache::VerIterator::TranslatedDescription() const
+{
+ pkgCache::DescIterator DescDefault = DescriptionList();
+ pkgCache::DescIterator Desc = DescDefault;
+ for (; Desc.end() == false; Desc++)
+ if (pkgIndexFile::LanguageCode() == Desc.LanguageCode())
+ break;
+ if (Desc.end() == true) Desc = DescDefault;
+ return Desc;
+};
+
+ /*}}}*/
diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h
index 587d97534..59d5003bb 100644
--- a/apt-pkg/pkgcache.h
+++ b/apt-pkg/pkgcache.h
@@ -19,9 +19,6 @@
#ifndef PKGLIB_PKGCACHE_H
#define PKGLIB_PKGCACHE_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/pkgcache.h"
-#endif
#include <string>
#include <time.h>
@@ -38,32 +35,42 @@ class pkgCache
struct Package;
struct PackageFile;
struct Version;
+ struct Description;
struct Provides;
struct Dependency;
struct StringItem;
struct VerFile;
+ struct DescFile;
// Iterators
class PkgIterator;
class VerIterator;
+ class DescIterator;
class DepIterator;
class PrvIterator;
class PkgFileIterator;
class VerFileIterator;
+ class DescFileIterator;
friend class PkgIterator;
friend class VerIterator;
+ friend class DescInterator;
friend class DepIterator;
friend class PrvIterator;
friend class PkgFileIterator;
friend class VerFileIterator;
+ friend class DescFileIterator;
class Namespace;
// These are all the constants used in the cache structures
+
+ // WARNING - if you change these lists you must also edit
+ // the stringification in pkgcache.cc and also consider whether
+ // the cache file will become incompatible.
struct Dep
{
enum DepType {Depends=1,PreDepends=2,Suggests=3,Recommends=4,
- Conflicts=5,Replaces=6,Obsoletes=7};
+ Conflicts=5,Replaces=6,Obsoletes=7,DpkgBreaks=8};
enum DepCompareOp {Or=0x10,NoOp=0,LessEq=0x1,GreaterEq=0x2,Less=0x3,
Greater=0x4,Equals=0x5,NotEquals=0x6};
};
@@ -74,7 +81,8 @@ class pkgCache
enum PkgSelectedState {Unknown=0,Install=1,Hold=2,DeInstall=3,Purge=4};
enum PkgInstState {Ok=0,ReInstReq=1,HoldInst=2,HoldReInstReq=3};
enum PkgCurrentState {NotInstalled=0,UnPacked=1,HalfConfigured=2,
- HalfInstalled=4,ConfigFiles=5,Installed=6};
+ HalfInstalled=4,ConfigFiles=5,Installed=6,
+ TriggersAwaited=7,TriggersPending=8};
};
struct Flag
@@ -98,8 +106,10 @@ class pkgCache
Header *HeaderP;
Package *PkgP;
VerFile *VerFileP;
+ DescFile *DescFileP;
PackageFile *PkgFileP;
Version *VerP;
+ Description *DescP;
Provides *ProvideP;
Dependency *DepP;
StringItem *StringItemP;
@@ -151,16 +161,20 @@ struct pkgCache::Header
unsigned short PackageSz;
unsigned short PackageFileSz;
unsigned short VersionSz;
+ unsigned short DescriptionSz;
unsigned short DependencySz;
unsigned short ProvidesSz;
unsigned short VerFileSz;
+ unsigned short DescFileSz;
// Structure counts
unsigned long PackageCount;
unsigned long VersionCount;
+ unsigned long DescriptionCount;
unsigned long DependsCount;
unsigned long PackageFileCount;
unsigned long VerFileCount;
+ unsigned long DescFileCount;
unsigned long ProvidesCount;
// Offsets
@@ -169,10 +183,11 @@ struct pkgCache::Header
map_ptrloc VerSysName; // StringTable
map_ptrloc Architecture; // StringTable
unsigned long MaxVerFileSize;
+ unsigned long MaxDescFileSize;
/* Allocation pools, there should be one of these for each structure
excluding the header */
- DynamicMMap::Pool Pools[7];
+ DynamicMMap::Pool Pools[8];
// Rapid package name lookup
map_ptrloc HashTable[2*1048];
@@ -193,7 +208,7 @@ struct pkgCache::Package
map_ptrloc NextPackage; // Package
map_ptrloc RevDepends; // Dependency
map_ptrloc ProvidesList; // Provides
-
+
// Install/Remove/Purge etc
unsigned char SelectedState; // What
unsigned char InstState; // Flags
@@ -232,6 +247,14 @@ struct pkgCache::VerFile
unsigned short Size;
};
+struct pkgCache::DescFile
+{
+ map_ptrloc File; // PackageFile
+ map_ptrloc NextFile; // PkgVerFile
+ map_ptrloc Offset; // File offset
+ unsigned short Size;
+};
+
struct pkgCache::Version
{
map_ptrloc VerStr; // Stringtable
@@ -241,6 +264,7 @@ struct pkgCache::Version
// Lists
map_ptrloc FileList; // VerFile
map_ptrloc NextVer; // Version
+ map_ptrloc DescriptionList; // Description
map_ptrloc DependsList; // Dependency
map_ptrloc ParentPkg; // Package
map_ptrloc ProvidesList; // Provides
@@ -252,6 +276,22 @@ struct pkgCache::Version
unsigned char Priority;
};
+struct pkgCache::Description
+{
+ // Language Code store the description translation language code. If
+ // the value has a 0 lenght then this is readed using the Package
+ // file else the Translation-CODE are used.
+ map_ptrloc language_code; // StringTable
+ map_ptrloc md5sum; // StringTable
+
+ // Linked list
+ map_ptrloc FileList; // DescFile
+ map_ptrloc NextDesc; // Description
+ map_ptrloc ParentPkg; // Package
+
+ unsigned short ID;
+};
+
struct pkgCache::Dependency
{
map_ptrloc Version; // Stringtable
@@ -299,11 +339,13 @@ class pkgCache::Namespace
typedef pkgCache::PkgIterator PkgIterator;
typedef pkgCache::VerIterator VerIterator;
+ typedef pkgCache::DescIterator DescIterator;
typedef pkgCache::DepIterator DepIterator;
typedef pkgCache::PrvIterator PrvIterator;
typedef pkgCache::PkgFileIterator PkgFileIterator;
typedef pkgCache::VerFileIterator VerFileIterator;
typedef pkgCache::Version Version;
+ typedef pkgCache::Description Description;
typedef pkgCache::Package Package;
typedef pkgCache::Header Header;
typedef pkgCache::Dep Dep;
diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc
index de854bee5..d00cd4e64 100644
--- a/apt-pkg/pkgcachegen.cc
+++ b/apt-pkg/pkgcachegen.cc
@@ -10,10 +10,6 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/pkgcachegen.h"
-#endif
-
#define APT_COMPATIBILITY 986
#include <apt-pkg/pkgcachegen.h>
@@ -26,6 +22,8 @@
#include <apt-pkg/sptr.h>
#include <apt-pkg/pkgsystem.h>
+#include <apt-pkg/tagfile.h>
+
#include <apti18n.h>
#include <vector>
@@ -125,16 +123,46 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
string Version = List.Version();
if (Version.empty() == true)
{
+ // we first process the package, then the descriptions
+ // (this has the bonus that we get MMap error when we run out
+ // of MMap space)
if (List.UsePackage(Pkg,pkgCache::VerIterator(Cache)) == false)
return _error->Error(_("Error occurred while processing %s (UsePackage1)"),
PackageName.c_str());
+
+ // Find the right version to write the description
+ MD5SumValue CurMd5 = List.Description_md5();
+ pkgCache::VerIterator Ver = Pkg.VersionList();
+ map_ptrloc *LastVer = &Pkg->VersionList;
+
+ for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++)
+ {
+ pkgCache::DescIterator Desc = Ver.DescriptionList();
+ map_ptrloc *LastDesc = &Ver->DescriptionList;
+
+ for (; Desc.end() == false; LastDesc = &Desc->NextDesc, Desc++)
+ {
+
+ if (MD5SumValue(Desc.md5()) == CurMd5)
+ {
+ // Add new description
+ *LastDesc = NewDescription(Desc, List.DescriptionLanguage(), CurMd5, *LastDesc);
+ Desc->ParentPkg = Pkg.Index();
+
+ if (NewFileDesc(Desc,List) == false)
+ return _error->Error(_("Error occurred while processing %s (NewFileDesc1)"),PackageName.c_str());
+ break;
+ }
+ }
+ }
+
continue;
}
pkgCache::VerIterator Ver = Pkg.VersionList();
- map_ptrloc *Last = &Pkg->VersionList;
+ map_ptrloc *LastVer = &Pkg->VersionList;
int Res = 1;
- for (; Ver.end() == false; Last = &Ver->NextVer, Ver++)
+ for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++)
{
Res = Cache.VS->CmpVersion(Version,Ver.VerStr());
if (Res >= 0)
@@ -168,7 +196,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
// Skip to the end of the same version set.
if (Res == 0)
{
- for (; Ver.end() == false; Last = &Ver->NextVer, Ver++)
+ for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++)
{
Res = Cache.VS->CmpVersion(Version,Ver.VerStr());
if (Res != 0)
@@ -177,9 +205,10 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
}
// Add a new version
- *Last = NewVersion(Ver,Version,*Last);
+ *LastVer = NewVersion(Ver,Version,*LastVer);
Ver->ParentPkg = Pkg.Index();
Ver->Hash = Hash;
+
if (List.NewVersion(Ver) == false)
return _error->Error(_("Error occurred while processing %s (NewVersion1)"),
PackageName.c_str());
@@ -199,6 +228,21 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
FoundFileDeps |= List.HasFileDeps();
return true;
}
+
+ /* Record the Description data. Description data always exist in
+ Packages and Translation-* files. */
+ pkgCache::DescIterator Desc = Ver.DescriptionList();
+ map_ptrloc *LastDesc = &Ver->DescriptionList;
+
+ // Skip to the end of description set
+ for (; Desc.end() == false; LastDesc = &Desc->NextDesc, Desc++);
+
+ // Add new description
+ *LastDesc = NewDescription(Desc, List.DescriptionLanguage(), List.Description_md5(), *LastDesc);
+ Desc->ParentPkg = Pkg.Index();
+
+ if (NewFileDesc(Desc,List) == false)
+ return _error->Error(_("Error occurred while processing %s (NewFileDesc2)"),PackageName.c_str());
}
FoundFileDeps |= List.HasFileDeps();
@@ -209,6 +253,9 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
if (Cache.HeaderP->VersionCount >= (1ULL<<(sizeof(Cache.VerP->ID)*8))-1)
return _error->Error(_("Wow, you exceeded the number of versions "
"this APT is capable of."));
+ if (Cache.HeaderP->DescriptionCount >= (1ULL<<(sizeof(Cache.DescP->ID)*8))-1)
+ return _error->Error(_("Wow, you exceeded the number of descriptions "
+ "this APT is capable of."));
if (Cache.HeaderP->DependsCount >= (1ULL<<(sizeof(Cache.DepP->ID)*8))-1ULL)
return _error->Error(_("Wow, you exceeded the number of dependencies "
"this APT is capable of."));
@@ -271,7 +318,7 @@ bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name
Pkg = Cache.FindPkg(Name);
if (Pkg.end() == false)
return true;
-
+
// Get a structure
unsigned long Package = Map.Allocate(sizeof(pkgCache::Package));
if (Package == 0)
@@ -349,6 +396,62 @@ unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver,
return Version;
}
/*}}}*/
+// CacheGenerator::NewFileDesc - Create a new File<->Desc association /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool pkgCacheGenerator::NewFileDesc(pkgCache::DescIterator &Desc,
+ ListParser &List)
+{
+ if (CurrentFile == 0)
+ return true;
+
+ // Get a structure
+ unsigned long DescFile = Map.Allocate(sizeof(pkgCache::DescFile));
+ if (DescFile == 0)
+ return 0;
+
+ pkgCache::DescFileIterator DF(Cache,Cache.DescFileP + DescFile);
+ DF->File = CurrentFile - Cache.PkgFileP;
+
+ // Link it to the end of the list
+ map_ptrloc *Last = &Desc->FileList;
+ for (pkgCache::DescFileIterator D = Desc.FileList(); D.end() == false; D++)
+ Last = &D->NextFile;
+
+ DF->NextFile = *Last;
+ *Last = DF.Index();
+
+ DF->Offset = List.Offset();
+ DF->Size = List.Size();
+ if (Cache.HeaderP->MaxDescFileSize < DF->Size)
+ Cache.HeaderP->MaxDescFileSize = DF->Size;
+ Cache.HeaderP->DescFileCount++;
+
+ return true;
+}
+ /*}}}*/
+// CacheGenerator::NewDescription - Create a new Description /*{{{*/
+// ---------------------------------------------------------------------
+/* This puts a description structure in the linked list */
+map_ptrloc pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc,
+ const string &Lang, const MD5SumValue &md5sum,
+ map_ptrloc Next)
+{
+ // Get a structure
+ map_ptrloc Description = Map.Allocate(sizeof(pkgCache::Description));
+ if (Description == 0)
+ return 0;
+
+ // Fill it in
+ Desc = pkgCache::DescIterator(Cache,Cache.DescP + Description);
+ Desc->NextDesc = Next;
+ Desc->ID = Cache.HeaderP->DescriptionCount++;
+ Desc->language_code = Map.WriteString(Lang);
+ Desc->md5sum = Map.WriteString(md5sum.Value());
+
+ return Description;
+}
+ /*}}}*/
// ListParser::NewDepends - Create a dependency element /*{{{*/
// ---------------------------------------------------------------------
/* This creates a dependency element in the tree. It is linked to the
@@ -571,8 +674,10 @@ static bool CheckValidity(const string &CacheFile, FileIterator Start,
if ((*Start)->Exists() == false)
{
+#if 0 // mvo: we no longer give a message here (Default Sources spec)
_error->WarningE("stat",_("Couldn't stat source package list %s"),
(*Start)->Describe().c_str());
+#endif
continue;
}
@@ -580,7 +685,7 @@ static bool CheckValidity(const string &CacheFile, FileIterator Start,
pkgCache::PkgFileIterator File = (*Start)->FindInCache(Cache);
if (File.end() == true)
return false;
-
+
Visited[File->ID] = true;
}
@@ -676,7 +781,7 @@ static bool BuildCache(pkgCacheGenerator &Gen,
bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
MMap **OutMap,bool AllowMem)
{
- unsigned long MapSize = _config->FindI("APT::Cache-Limit",12*1024*1024);
+ unsigned long MapSize = _config->FindI("APT::Cache-Limit",24*1024*1024);
vector<pkgIndexFile *> Files;
for (vector<metaIndex *>::const_iterator i = List.begin();
@@ -823,7 +928,7 @@ bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
/* */
bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutMap)
{
- unsigned long MapSize = _config->FindI("APT::Cache-Limit",8*1024*1024);
+ unsigned long MapSize = _config->FindI("APT::Cache-Limit",20*1024*1024);
vector<pkgIndexFile *> Files;
unsigned long EndOfSource = Files.size();
if (_system->AddStatusFiles(Files) == false)
diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h
index 9a729eea4..b6715294a 100644
--- a/apt-pkg/pkgcachegen.h
+++ b/apt-pkg/pkgcachegen.h
@@ -19,11 +19,9 @@
#ifndef PKGLIB_PKGCACHEGEN_H
#define PKGLIB_PKGCACHEGEN_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/pkgcachegen.h"
-#endif
#include <apt-pkg/pkgcache.h>
+#include <apt-pkg/md5.h>
class pkgSourceList;
class OpProgress;
@@ -53,9 +51,11 @@ class pkgCacheGenerator
// Flag file dependencies
bool FoundFileDeps;
- bool NewPackage(pkgCache::PkgIterator &Pkg,const string &Pkg);
+ bool NewPackage(pkgCache::PkgIterator &Pkg,const string &PkgName);
bool NewFileVer(pkgCache::VerIterator &Ver,ListParser &List);
+ bool NewFileDesc(pkgCache::DescIterator &Desc,ListParser &List);
unsigned long NewVersion(pkgCache::VerIterator &Ver,const string &VerStr,unsigned long Next);
+ map_ptrloc NewDescription(pkgCache::DescIterator &Desc,const string &Lang,const MD5SumValue &md5sum,map_ptrloc Next);
public:
@@ -108,6 +108,9 @@ class pkgCacheGenerator::ListParser
virtual string Package() = 0;
virtual string Version() = 0;
virtual bool NewVersion(pkgCache::VerIterator Ver) = 0;
+ virtual string Description() = 0;
+ virtual string DescriptionLanguage() = 0;
+ virtual MD5SumValue Description_md5() = 0;
virtual unsigned short VersionHash() = 0;
virtual bool UsePackage(pkgCache::PkgIterator Pkg,
pkgCache::VerIterator Ver) = 0;
diff --git a/apt-pkg/pkgrecords.cc b/apt-pkg/pkgrecords.cc
index 9c2655d6a..e506de73a 100644
--- a/apt-pkg/pkgrecords.cc
+++ b/apt-pkg/pkgrecords.cc
@@ -9,9 +9,6 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/pkgrecords.h"
-#endif
#include <apt-pkg/pkgrecords.h>
#include <apt-pkg/indexfile.h>
#include <apt-pkg/error.h>
@@ -23,25 +20,23 @@
// Records::pkgRecords - Constructor /*{{{*/
// ---------------------------------------------------------------------
/* This will create the necessary structures to access the status files */
-pkgRecords::pkgRecords(pkgCache &Cache) : Cache(Cache), Files(0)
+pkgRecords::pkgRecords(pkgCache &Cache) : Cache(Cache),
+ Files(Cache.HeaderP->PackageFileCount)
{
- Files = new Parser *[Cache.HeaderP->PackageFileCount];
- memset(Files,0,sizeof(*Files)*Cache.HeaderP->PackageFileCount);
-
- for (pkgCache::PkgFileIterator I = Cache.FileBegin();
- I.end() == false; I++)
+ for (pkgCache::PkgFileIterator I = Cache.FileBegin();
+ I.end() == false; I++)
{
const pkgIndexFile::Type *Type = pkgIndexFile::Type::GetType(I.IndexType());
if (Type == 0)
{
- _error->Error(_("Index file type '%s' is not supported"),I.IndexType());
- return;
+ _error->Error(_("Index file type '%s' is not supported"),I.IndexType());
+ return;
}
Files[I->ID] = Type->CreatePkgParser(I);
if (Files[I->ID] == 0)
- return;
- }
+ return;
+ }
}
/*}}}*/
// Records::~pkgRecords - Destructor /*{{{*/
@@ -49,9 +44,12 @@ pkgRecords::pkgRecords(pkgCache &Cache) : Cache(Cache), Files(0)
/* */
pkgRecords::~pkgRecords()
{
- for (unsigned I = 0; I != Cache.HeaderP->PackageFileCount; I++)
- delete Files[I];
- delete [] Files;
+ for ( vector<Parser*>::iterator it = Files.begin();
+ it != Files.end();
+ ++it)
+ {
+ delete *it;
+ }
}
/*}}}*/
// Records::Lookup - Get a parser for the package version file /*{{{*/
@@ -63,3 +61,12 @@ pkgRecords::Parser &pkgRecords::Lookup(pkgCache::VerFileIterator const &Ver)
return *Files[Ver.File()->ID];
}
/*}}}*/
+// Records::Lookup - Get a parser for the package description file /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+pkgRecords::Parser &pkgRecords::Lookup(pkgCache::DescFileIterator const &Desc)
+{
+ Files[Desc.File()->ID]->Jump(Desc);
+ return *Files[Desc.File()->ID];
+}
+ /*}}}*/
diff --git a/apt-pkg/pkgrecords.h b/apt-pkg/pkgrecords.h
index 08f004414..17f3b1569 100644
--- a/apt-pkg/pkgrecords.h
+++ b/apt-pkg/pkgrecords.h
@@ -17,12 +17,10 @@
#ifndef PKGLIB_PKGRECORDS_H
#define PKGLIB_PKGRECORDS_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/pkgrecords.h"
-#endif
#include <apt-pkg/pkgcache.h>
#include <apt-pkg/fileutl.h>
+#include <vector>
class pkgRecords
{
@@ -32,12 +30,13 @@ class pkgRecords
private:
pkgCache &Cache;
- Parser **Files;
-
+ std::vector<Parser *>Files;
+
public:
// Lookup function
Parser &Lookup(pkgCache::VerFileIterator const &Ver);
+ Parser &Lookup(pkgCache::DescFileIterator const &Desc);
// Construct destruct
pkgRecords(pkgCache &Cache);
@@ -49,6 +48,7 @@ class pkgRecords::Parser
protected:
virtual bool Jump(pkgCache::VerFileIterator const &Ver) = 0;
+ virtual bool Jump(pkgCache::DescFileIterator const &Desc) = 0;
public:
friend class pkgRecords;
@@ -57,13 +57,16 @@ class pkgRecords::Parser
virtual string FileName() {return string();};
virtual string MD5Hash() {return string();};
virtual string SHA1Hash() {return string();};
+ virtual string SHA256Hash() {return string();};
virtual string SourcePkg() {return string();};
+ virtual string SourceVer() {return string();};
// These are some general stats about the package
virtual string Maintainer() {return string();};
virtual string ShortDesc() {return string();};
virtual string LongDesc() {return string();};
virtual string Name() {return string();};
+ virtual string Homepage() {return string();}
// The record in binary form
virtual void GetRec(const char *&Start,const char *&Stop) {Start = Stop = 0;};
diff --git a/apt-pkg/pkgsystem.cc b/apt-pkg/pkgsystem.cc
index 86174a44f..6dd2d3ee4 100644
--- a/apt-pkg/pkgsystem.cc
+++ b/apt-pkg/pkgsystem.cc
@@ -10,13 +10,10 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/pkgsystem.h"
-#endif
-
#include <apt-pkg/pkgsystem.h>
#include <apt-pkg/policy.h>
#include <cassert>
+#include <cstring>
/*}}}*/
pkgSystem *_system = 0;
diff --git a/apt-pkg/pkgsystem.h b/apt-pkg/pkgsystem.h
index a7d555140..246762e0b 100644
--- a/apt-pkg/pkgsystem.h
+++ b/apt-pkg/pkgsystem.h
@@ -37,9 +37,6 @@
#ifndef PKGLIB_PKGSYSTEM_H
#define PKGLIB_PKGSYSTEM_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/pkgsystem.h"
-#endif
#include <apt-pkg/depcache.h>
#include <vector>
diff --git a/apt-pkg/policy.cc b/apt-pkg/policy.cc
index d8b8825c2..8b083fd44 100644
--- a/apt-pkg/policy.cc
+++ b/apt-pkg/policy.cc
@@ -23,9 +23,6 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/policy.h"
-#endif
#include <apt-pkg/policy.h>
#include <apt-pkg/configuration.h>
#include <apt-pkg/tagfile.h>
@@ -36,6 +33,7 @@
#include <apti18n.h>
#include <iostream>
+#include <sstream>
/*}}}*/
using namespace std;
@@ -300,7 +298,13 @@ bool ReadPinFile(pkgPolicy &Plcy,string File)
continue;
}
- Plcy.CreatePin(Type,Name,string(Word,End),priority);
+ istringstream s(Name);
+ string pkg;
+ while(!s.eof())
+ {
+ s >> pkg;
+ Plcy.CreatePin(Type, pkg, string(Word,End),priority);
+ };
}
Plcy.InitDefaults();
diff --git a/apt-pkg/policy.h b/apt-pkg/policy.h
index 40ebd3f70..d5f3b2f75 100644
--- a/apt-pkg/policy.h
+++ b/apt-pkg/policy.h
@@ -33,9 +33,6 @@
#ifndef PKGLIB_POLICY_H
#define PKGLIB_POLICY_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/policy.h"
-#endif
#include <apt-pkg/depcache.h>
#include <apt-pkg/versionmatch.h>
diff --git a/apt-pkg/sourcelist.cc b/apt-pkg/sourcelist.cc
index e3b4d94f8..fea645078 100644
--- a/apt-pkg/sourcelist.cc
+++ b/apt-pkg/sourcelist.cc
@@ -8,10 +8,6 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/sourcelist.h"
-#endif
-
#include <apt-pkg/sourcelist.h>
#include <apt-pkg/error.h>
#include <apt-pkg/fileutl.h>
diff --git a/apt-pkg/sourcelist.h b/apt-pkg/sourcelist.h
index 123ae6984..b9e4389ed 100644
--- a/apt-pkg/sourcelist.h
+++ b/apt-pkg/sourcelist.h
@@ -35,9 +35,6 @@
using std::string;
using std::vector;
-#ifdef __GNUG__
-#pragma interface "apt-pkg/sourcelist.h"
-#endif
class pkgAquire;
class pkgSourceList
diff --git a/apt-pkg/srcrecords.cc b/apt-pkg/srcrecords.cc
index 6cac477ef..5e40ae624 100644
--- a/apt-pkg/srcrecords.cc
+++ b/apt-pkg/srcrecords.cc
@@ -11,10 +11,6 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/srcrecords.h"
-#endif
-
#include <apt-pkg/srcrecords.h>
#include <apt-pkg/error.h>
#include <apt-pkg/sourcelist.h>
diff --git a/apt-pkg/srcrecords.h b/apt-pkg/srcrecords.h
index 3e2112549..99cbc6060 100644
--- a/apt-pkg/srcrecords.h
+++ b/apt-pkg/srcrecords.h
@@ -13,9 +13,6 @@
#ifndef PKGLIB_SRCRECORDS_H
#define PKGLIB_SRCRECORDS_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/srcrecords.h"
-#endif
#include <string>
#include <vector>
diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc
index dc1ba3f9e..893cb8ee7 100644
--- a/apt-pkg/tagfile.cc
+++ b/apt-pkg/tagfile.cc
@@ -11,10 +11,6 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/tagfile.h"
-#endif
-
#include <apt-pkg/tagfile.h>
#include <apt-pkg/error.h>
#include <apt-pkg/strutl.h>
@@ -35,20 +31,20 @@ pkgTagFile::pkgTagFile(FileFd *pFd,unsigned long Size) :
Fd(*pFd),
Size(Size)
{
- 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 ();
+ Buffer = new char[Size];
+ Start = End = Buffer;
+ Done = false;
iOffset = 0;
+ Fill();
}
/*}}}*/
// TagFile::~pkgTagFile - Destructor /*{{{*/
@@ -56,21 +52,55 @@ pkgTagFile::pkgTagFile(FileFd *pFd,unsigned long Size) :
/* */
pkgTagFile::~pkgTagFile()
{
- delete Map;
+ delete [] Buffer;
}
/*}}}*/
-// TagFile::Step - Advance to the next section /*{{{*/
+// TagFile::Resize - Resize the internal buffer /*{{{*/
// ---------------------------------------------------------------------
-/* If the Section Scanner fails we refill the buffer and try again. */
-bool pkgTagFile::Step(pkgTagSection &Tag)
+/* Resize the internal buffer (double it in size). Fail if a maximum size
+ * size is reached.
+ */
+bool pkgTagFile::Resize()
{
- if (Start == End)
+ char *tmp;
+ unsigned long EndSize = End - Start;
+
+ // fail is the buffer grows too big
+ if(Size > 1024*1024+1)
return false;
- if (Tag.Scan(Start,End - Start) == false)
+ // get new buffer and use it
+ tmp = new char[2*Size];
+ memcpy(tmp, Buffer, Size);
+ Size = Size*2;
+ delete [] Buffer;
+ Buffer = tmp;
+
+ // update the start/end pointers to the new buffer
+ Start = Buffer;
+ End = Start + EndSize;
+ return true;
+}
+
+// TagFile::Step - Advance to the next section /*{{{*/
+// ---------------------------------------------------------------------
+/* If the Section Scanner fails we refill the buffer and try again.
+ * If that fails too, double the buffer size and try again until a
+ * maximum buffer is reached.
+ */
+bool pkgTagFile::Step(pkgTagSection &Tag)
+{
+ while (Tag.Scan(Start,End - Start) == false)
{
- 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))
+ break;
+
+ if (Resize() == false)
+ return _error->Error(_("Unable to parse package file %s (1)"),
+ Fd.Name().c_str());
}
Start += Tag.size();
iOffset += Tag.size();
@@ -79,6 +109,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
@@ -96,7 +170,20 @@ bool pkgTagFile::Jump(pkgTagSection &Tag,unsigned long Offset)
// Reposition and reload..
iOffset = Offset;
- Start = Buffer + iOffset;
+ 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;
if (Tag.Scan(Start,End - Start) == false)
return _error->Error(_("Unable to parse package file %s (2)"),Fd.Name().c_str());
@@ -108,12 +195,12 @@ bool pkgTagFile::Jump(pkgTagSection &Tag,unsigned long Offset)
// ---------------------------------------------------------------------
/* This looks for the first double new line in the data stream. It also
indexes the tags in the section. This very simple hash function for the
- first 3 letters gives very good performance on the debian package files */
+ last 8 letters gives very good performance on the debian package files */
inline static unsigned long AlphaHash(const char *Text, const char *End = 0)
{
unsigned long Res = 0;
for (; Text != End && *Text != ':' && *Text != 0; Text++)
- Res = (unsigned long)(*Text) ^ (Res << 2);
+ Res = ((unsigned long)(*Text) & 0xDF) ^ (Res << 1);
return Res & 0xFF;
}
@@ -123,7 +210,7 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength)
Stop = Section = Start;
memset(AlphaIndexes,0,sizeof(AlphaIndexes));
- if (Stop == 0 || MaxLength == 0)
+ if (Stop == 0)
return false;
TagCount = 0;
@@ -154,12 +241,6 @@ 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;
}
/*}}}*/
@@ -338,11 +419,13 @@ static const char *iTFRewritePackageOrder[] = {
"Recommends",
"Suggests",
"Conflicts",
+ "Breaks",
"Conffiles",
"Filename",
"Size",
"MD5Sum",
- "SHA1Sum",
+ "SHA1",
+ "SHA256",
"MSDOS-Filename", // Obsolete
"Description",
0};
diff --git a/apt-pkg/tagfile.h b/apt-pkg/tagfile.h
index 5cff2681c..6536932dd 100644
--- a/apt-pkg/tagfile.h
+++ b/apt-pkg/tagfile.h
@@ -20,12 +20,8 @@
#ifndef PKGLIB_TAGFILE_H
#define PKGLIB_TAGFILE_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/tagfile.h"
-#endif
#include <apt-pkg/fileutl.h>
-#include <apt-pkg/mmap.h>
#include <stdio.h>
class pkgTagSection
@@ -34,8 +30,8 @@ class pkgTagSection
const char *Stop;
// We have a limit of 256 tags per section.
- unsigned short Indexes[256];
- unsigned short AlphaIndexes[0x100];
+ unsigned int Indexes[256];
+ unsigned int AlphaIndexes[0x100];
unsigned int TagCount;
@@ -70,13 +66,16 @@ class pkgTagSection
class pkgTagFile
{
FileFd &Fd;
- MMap *Map;
char *Buffer;
char *Start;
char *End;
+ bool Done;
unsigned long iOffset;
unsigned long Size;
-
+
+ bool Fill();
+ bool Resize();
+
public:
bool Step(pkgTagSection &Section);
diff --git a/apt-pkg/vendor.cc b/apt-pkg/vendor.cc
index d0392ebdb..2350afe69 100644
--- a/apt-pkg/vendor.cc
+++ b/apt-pkg/vendor.cc
@@ -1,7 +1,3 @@
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/vendor.h"
-#endif
-
#include <iostream>
#include <apt-pkg/error.h>
#include <apt-pkg/vendor.h>
diff --git a/apt-pkg/vendor.h b/apt-pkg/vendor.h
index 033bb96e8..2d39fd15f 100644
--- a/apt-pkg/vendor.h
+++ b/apt-pkg/vendor.h
@@ -4,9 +4,6 @@
#include <vector>
#include <map>
-#ifdef __GNUG__
-#pragma interface "apt-pkg/vendor.h"
-#endif
using std::string;
diff --git a/apt-pkg/vendorlist.cc b/apt-pkg/vendorlist.cc
index 72694dd75..8e5d09e8a 100644
--- a/apt-pkg/vendorlist.cc
+++ b/apt-pkg/vendorlist.cc
@@ -113,7 +113,7 @@ bool pkgVendorList::CreateList(Configuration& Cnf)
const Vendor* pkgVendorList::LookupFingerprint(string Fingerprint)
{
- for (const_iterator I = begin(); I != end(); ++I)
+ for (const_iterator I = VendorList.begin(); I != VendorList.end(); ++I)
{
if ((*I)->LookupFingerprint(Fingerprint) != "")
return *I;
diff --git a/apt-pkg/vendorlist.h b/apt-pkg/vendorlist.h
index 7f96fc766..ff2f4ed5d 100644
--- a/apt-pkg/vendorlist.h
+++ b/apt-pkg/vendorlist.h
@@ -21,9 +21,6 @@
using std::string;
using std::vector;
-#ifdef __GNUG__
-#pragma interface "apt-pkg/vendorlist.h"
-#endif
class pkgVendorList
{
diff --git a/apt-pkg/version.cc b/apt-pkg/version.cc
index db340c11f..42e449d36 100644
--- a/apt-pkg/version.cc
+++ b/apt-pkg/version.cc
@@ -8,10 +8,6 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/version.h"
-#endif
-
#include <apt-pkg/version.h>
#include <apt-pkg/pkgcache.h>
diff --git a/apt-pkg/version.h b/apt-pkg/version.h
index 071dba3e2..49c53a93a 100644
--- a/apt-pkg/version.h
+++ b/apt-pkg/version.h
@@ -20,9 +20,6 @@
#ifndef PKGLIB_VERSION_H
#define PKGLIB_VERSION_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/version.h"
-#endif
#include <apt-pkg/strutl.h>
#include <string>
diff --git a/apt-pkg/versionmatch.cc b/apt-pkg/versionmatch.cc
index 9e341852b..4a426809c 100644
--- a/apt-pkg/versionmatch.cc
+++ b/apt-pkg/versionmatch.cc
@@ -11,9 +11,6 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/versionmatch.h"
-#endif
#include <apt-pkg/versionmatch.h>
#include <apt-pkg/strutl.h>
diff --git a/apt-pkg/versionmatch.h b/apt-pkg/versionmatch.h
index 7ca39cbe8..fe264aa46 100644
--- a/apt-pkg/versionmatch.h
+++ b/apt-pkg/versionmatch.h
@@ -31,9 +31,6 @@
#ifndef PKGLIB_VERSIONMATCH_H
#define PKGLIB_VERSIONMATCH_H
-#ifdef __GNUG__
-#pragma interface "apt-pkg/versionmatch.h"
-#endif
#include <string>
#include <apt-pkg/pkgcache.h>