summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Vogt <mvo@debian.org>2014-05-14 18:04:48 +0200
committerMichael Vogt <mvo@debian.org>2014-05-14 18:04:48 +0200
commite110d7bf5675f484c06b82f621ac98bedc464865 (patch)
tree70ce5da7ad75ccbaf4b30cf4809209993ba98b23
parent0b58b3f8917a49d83154fd3173bca36c1d617ef0 (diff)
parent4f6d26b4d41474aa390329b7e9cb167eb70b2821 (diff)
Merge remote-tracking branch 'donkult/debian/experimental' into debian/experimental
Conflicts: apt-pkg/acquire-item.cc apt-pkg/acquire-item.h
-rw-r--r--apt-pkg/acquire-item.cc216
-rw-r--r--apt-pkg/acquire-item.h198
-rw-r--r--apt-pkg/acquire-method.cc48
-rw-r--r--apt-pkg/acquire-method.h10
-rw-r--r--apt-pkg/acquire-worker.cc40
-rw-r--r--apt-pkg/aptconfiguration.cc2
-rw-r--r--apt-pkg/contrib/hashes.cc213
-rw-r--r--apt-pkg/contrib/hashes.h165
-rw-r--r--apt-pkg/deb/deblistparser.cc40
-rw-r--r--apt-pkg/deb/deblistparser.h4
-rw-r--r--apt-pkg/deb/debmetaindex.cc2
-rw-r--r--apt-pkg/deb/debrecords.cc101
-rw-r--r--apt-pkg/deb/debrecords.h12
-rw-r--r--apt-pkg/deb/debsrcrecords.cc170
-rw-r--r--apt-pkg/indexcopy.cc8
-rw-r--r--apt-pkg/indexrecords.cc2
-rw-r--r--apt-pkg/indexrecords.h12
-rw-r--r--apt-pkg/pkgcache.cc24
-rw-r--r--apt-pkg/pkgcache.h4
-rw-r--r--apt-pkg/pkgcachegen.cc99
-rw-r--r--apt-pkg/pkgcachegen.h7
-rw-r--r--apt-pkg/pkgrecords.h44
-rw-r--r--apt-pkg/srcrecords.h17
-rw-r--r--apt-pkg/tagfile.cc209
-rw-r--r--apt-pkg/tagfile.h63
-rw-r--r--apt-private/acqprogress.cc3
-rw-r--r--cmdline/apt-extracttemplates.cc13
-rw-r--r--cmdline/apt-get.cc19
-rw-r--r--doc/apt.conf.5.xml6
-rw-r--r--ftparchive/cachedb.cc194
-rw-r--r--ftparchive/cachedb.h31
-rw-r--r--ftparchive/writer.cc324
-rw-r--r--ftparchive/writer.h14
-rw-r--r--methods/server.cc46
-rw-r--r--methods/server.h2
-rw-r--r--test/integration/framework14
-rwxr-xr-xtest/integration/test-apt-ftparchive-cachedb4
-rwxr-xr-xtest/integration/test-apt-ftparchive-src-cachedb15
-rwxr-xr-xtest/integration/test-apt-sources-deb82248
-rwxr-xr-xtest/integration/test-bug-595691-empty-and-broken-archive-files2
-rwxr-xr-xtest/integration/test-bug-712435-missing-descriptions9
-rwxr-xr-xtest/integration/test-bug-722207-print-uris-even-if-very-quiet8
-rwxr-xr-xtest/integration/test-bug-745036-new-foreign-invalidates-cache29
-rwxr-xr-xtest/integration/test-bug-747261-arch-specific-conflicts51
-rwxr-xr-xtest/integration/test-debsrc-hashes77
-rwxr-xr-xtest/integration/test-http-pipeline-messup43
-rwxr-xr-xtest/integration/test-kernel-helper-autoremove2
-rwxr-xr-xtest/integration/test-pdiff-usage6
-rwxr-xr-xtest/integration/test-ubuntu-bug-1098738-apt-get-source-md5sum262
-rwxr-xr-xtest/integration/test-ubuntu-bug-346386-apt-get-update-paywall2
-rw-r--r--test/libapt/hashsums_test.cc149
-rw-r--r--test/libapt/tagfile_test.cc179
52 files changed, 2099 insertions, 1163 deletions
diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc
index b3d67de2c..99013d649 100644
--- a/apt-pkg/acquire-item.cc
+++ b/apt-pkg/acquire-item.cc
@@ -50,13 +50,24 @@
using namespace std;
+static void printHashSumComparision(std::string const &URI, HashStringList const &Expected, HashStringList const &Actual) /*{{{*/
+{
+ if (_config->FindB("Debug::Acquire::HashSumMismatch", false) == false)
+ return;
+ std::cerr << std::endl << URI << ":" << std::endl << " Expected Hash: " << std::endl;
+ for (HashStringList::const_iterator hs = Expected.begin(); hs != Expected.end(); ++hs)
+ std::cerr << "\t- " << hs->toStr() << std::endl;
+ std::cerr << " Actual Hash: " << std::endl;
+ for (HashStringList::const_iterator hs = Actual.begin(); hs != Actual.end(); ++hs)
+ std::cerr << "\t- " << hs->toStr() << std::endl;
+}
+ /*}}}*/
+
// Acquire::Item::Item - Constructor /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-pkgAcquire::Item::Item(pkgAcquire *Owner) : Owner(Owner), FileSize(0),
- PartialSize(0), Mode(0), ID(0), Complete(false),
- Local(false), QueueCounter(0),
- ExpectedAdditionalItems(0)
+pkgAcquire::Item::Item(pkgAcquire *Owner, HashStringList const &ExpectedHashes) :
+ Owner(Owner), FileSize(0), PartialSize(0), Mode(0), ID(0), Complete(false),
+ Local(false), QueueCounter(0), ExpectedAdditionalItems(0),
+ ExpectedHashes(ExpectedHashes)
{
Owner->Add(this);
Status = StatIdle;
@@ -118,7 +129,7 @@ void pkgAcquire::Item::Start(string /*Message*/,unsigned long long Size)
// Acquire::Item::Done - Item downloaded OK /*{{{*/
// ---------------------------------------------------------------------
/* */
-void pkgAcquire::Item::Done(string Message,unsigned long long Size,string /*Hash*/,
+void pkgAcquire::Item::Done(string Message,unsigned long long Size,HashStringList const &/*Hash*/,
pkgAcquire::MethodConfig * /*Cnf*/)
{
// We just downloaded something..
@@ -229,8 +240,8 @@ void pkgAcquire::Item::ReportMirrorFailure(string FailCode)
possibly query additional files */
pkgAcqSubIndex::pkgAcqSubIndex(pkgAcquire *Owner, string const &URI,
string const &URIDesc, string const &ShortDesc,
- HashString const &ExpectedHash)
- : Item(Owner), ExpectedHash(ExpectedHash)
+ HashStringList const &ExpectedHashes)
+ : Item(Owner, ExpectedHashes)
{
/* XXX: Beware: Currently this class does nothing (of value) anymore ! */
Debug = _config->FindB("Debug::pkgAcquire::SubIndex",false);
@@ -252,7 +263,7 @@ pkgAcqSubIndex::pkgAcqSubIndex(pkgAcquire *Owner, string const &URI,
// AcqSubIndex::Custom600Headers - Insert custom request headers /*{{{*/
// ---------------------------------------------------------------------
/* The only header we use is the last-modified header. */
-string pkgAcqSubIndex::Custom600Headers()
+string pkgAcqSubIndex::Custom600Headers() const
{
string Final = _config->FindDir("Dir::State::lists");
Final += URItoFileName(Desc.URI);
@@ -275,7 +286,7 @@ void pkgAcqSubIndex::Failed(string Message,pkgAcquire::MethodConfig * /*Cnf*/)/*
// No good Index is provided
}
/*}}}*/
-void pkgAcqSubIndex::Done(string Message,unsigned long long Size,string Md5Hash, /*{{{*/
+void pkgAcqSubIndex::Done(string Message,unsigned long long Size,HashStringList const &Hashes, /*{{{*/
pkgAcquire::MethodConfig *Cnf)
{
if(Debug)
@@ -297,7 +308,7 @@ void pkgAcqSubIndex::Done(string Message,unsigned long long Size,string Md5Hash,
return;
}
- Item::Done(Message,Size,Md5Hash,Cnf);
+ Item::Done(Message, Size, Hashes, Cnf);
string FinalFile = _config->FindDir("Dir::State::lists")+URItoFileName(Desc.URI);
@@ -343,10 +354,10 @@ bool pkgAcqSubIndex::ParseIndex(string const &IndexFile) /*{{{*/
* the original packages file
*/
pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner,
- IndexTarget const *Target,
- HashString ExpectedHash,
+ IndexTarget const * const Target,
+ HashStringList const &ExpectedHashes,
indexRecords *MetaIndexParser)
- : pkgAcqBaseIndex(Owner, Target, ExpectedHash, MetaIndexParser)
+ : pkgAcqBaseIndex(Owner, Target, ExpectedHashes, MetaIndexParser)
{
Debug = _config->FindB("Debug::pkgAcquire::Diffs",false);
@@ -391,7 +402,7 @@ pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner,
// AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/
// ---------------------------------------------------------------------
/* The only header we use is the last-modified header. */
-string pkgAcqDiffIndex::Custom600Headers()
+string pkgAcqDiffIndex::Custom600Headers() const
{
string Final = _config->FindDir("Dir::State::lists");
Final += URItoFileName(RealURI) + string(".IndexDiff");
@@ -444,7 +455,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile) /*{{{*/
std::clog << "Package file is up-to-date" << std::endl;
// list cleanup needs to know that this file as well as the already
// present index is ours, so we create an empty diff to save it for us
- new pkgAcqIndexDiffs(Owner, Target, ExpectedHash, MetaIndexParser,
+ new pkgAcqIndexDiffs(Owner, Target, ExpectedHashes, MetaIndexParser,
ServerSha1, available_patches);
return true;
}
@@ -531,7 +542,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile) /*{{{*/
if (pdiff_merge == false)
{
- new pkgAcqIndexDiffs(Owner, Target, ExpectedHash, MetaIndexParser,
+ new pkgAcqIndexDiffs(Owner, Target, ExpectedHashes, MetaIndexParser,
ServerSha1, available_patches);
}
else
@@ -539,7 +550,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile) /*{{{*/
std::vector<pkgAcqIndexMergeDiffs*> *diffs = new std::vector<pkgAcqIndexMergeDiffs*>(available_patches.size());
for(size_t i = 0; i < available_patches.size(); ++i)
(*diffs)[i] = new pkgAcqIndexMergeDiffs(Owner, Target,
- ExpectedHash,
+ ExpectedHashes,
MetaIndexParser,
available_patches[i],
diffs);
@@ -566,20 +577,20 @@ void pkgAcqDiffIndex::Failed(string Message,pkgAcquire::MethodConfig * /*Cnf*/)/
std::clog << "pkgAcqDiffIndex failed: " << Desc.URI << " with " << Message << std::endl
<< "Falling back to normal index file acquire" << std::endl;
- new pkgAcqIndex(Owner, Target, ExpectedHash, MetaIndexParser);
+ new pkgAcqIndex(Owner, Target, ExpectedHashes, MetaIndexParser);
Complete = false;
Status = StatDone;
Dequeue();
}
/*}}}*/
-void pkgAcqDiffIndex::Done(string Message,unsigned long long Size,string Md5Hash, /*{{{*/
+void pkgAcqDiffIndex::Done(string Message,unsigned long long Size,HashStringList const &Hashes, /*{{{*/
pkgAcquire::MethodConfig *Cnf)
{
if(Debug)
std::clog << "pkgAcqDiffIndex::Done(): " << Desc.URI << std::endl;
- Item::Done(Message,Size,Md5Hash,Cnf);
+ Item::Done(Message, Size, Hashes, Cnf);
string FinalFile;
FinalFile = _config->FindDir("Dir::State::lists")+URItoFileName(RealURI);
@@ -610,11 +621,11 @@ void pkgAcqDiffIndex::Done(string Message,unsigned long long Size,string Md5Hash
*/
pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire *Owner,
struct IndexTarget const * const Target,
- HashString ExpectedHash,
+ HashStringList const &ExpectedHashes,
indexRecords *MetaIndexParser,
string ServerSha1,
vector<DiffInfo> diffs)
- : pkgAcqBaseIndex(Owner, Target, ExpectedHash, MetaIndexParser),
+ : pkgAcqBaseIndex(Owner, Target, ExpectedHashes, MetaIndexParser),
available_patches(diffs), ServerSha1(ServerSha1)
{
@@ -646,7 +657,7 @@ void pkgAcqIndexDiffs::Failed(string Message,pkgAcquire::MethodConfig * /*Cnf*/)
if(Debug)
std::clog << "pkgAcqIndexDiffs failed: " << Desc.URI << " with " << Message << std::endl
<< "Falling back to normal index file acquire" << std::endl;
- new pkgAcqIndex(Owner, Target, ExpectedHash, MetaIndexParser);
+ new pkgAcqIndex(Owner, Target, ExpectedHashes, MetaIndexParser);
Finish();
}
/*}}}*/
@@ -660,7 +671,7 @@ void pkgAcqIndexDiffs::Finish(bool allDone)
DestFile = _config->FindDir("Dir::State::lists");
DestFile += URItoFileName(RealURI);
- if(!ExpectedHash.empty() && !ExpectedHash.VerifyFile(DestFile))
+ if(HashSums().usable() && !HashSums().VerifyFile(DestFile))
{
RenameOnError(HashSumMismatch);
Dequeue();
@@ -738,13 +749,13 @@ bool pkgAcqIndexDiffs::QueueNextDiff() /*{{{*/
return true;
}
/*}}}*/
-void pkgAcqIndexDiffs::Done(string Message,unsigned long long Size,string Md5Hash, /*{{{*/
+void pkgAcqIndexDiffs::Done(string Message,unsigned long long Size, HashStringList const &Hashes, /*{{{*/
pkgAcquire::MethodConfig *Cnf)
{
if(Debug)
std::clog << "pkgAcqIndexDiffs::Done(): " << Desc.URI << std::endl;
- Item::Done(Message,Size,Md5Hash,Cnf);
+ Item::Done(Message, Size, Hashes, Cnf);
string FinalFile;
FinalFile = _config->FindDir("Dir::State::lists")+URItoFileName(RealURI);
@@ -787,7 +798,7 @@ void pkgAcqIndexDiffs::Done(string Message,unsigned long long Size,string Md5Has
// see if there is more to download
if(available_patches.empty() == false) {
new pkgAcqIndexDiffs(Owner, Target,
- ExpectedHash, MetaIndexParser,
+ ExpectedHashes, MetaIndexParser,
ServerSha1, available_patches);
return Finish();
} else
@@ -798,11 +809,11 @@ void pkgAcqIndexDiffs::Done(string Message,unsigned long long Size,string Md5Has
// AcqIndexMergeDiffs::AcqIndexMergeDiffs - Constructor /*{{{*/
pkgAcqIndexMergeDiffs::pkgAcqIndexMergeDiffs(pkgAcquire *Owner,
struct IndexTarget const * const Target,
- HashString ExpectedHash,
+ HashStringList const &ExpectedHashes,
indexRecords *MetaIndexParser,
DiffInfo const &patch,
std::vector<pkgAcqIndexMergeDiffs*> const * const allPatches)
- : pkgAcqBaseIndex(Owner, Target, ExpectedHash, MetaIndexParser),
+ : pkgAcqBaseIndex(Owner, Target, ExpectedHashes, MetaIndexParser),
patch(patch), allPatches(allPatches), State(StateFetchDiff)
{
@@ -845,16 +856,16 @@ void pkgAcqIndexMergeDiffs::Failed(string Message,pkgAcquire::MethodConfig * /*C
// first failure means we should fallback
State = StateErrorDiff;
std::clog << "Falling back to normal index file acquire" << std::endl;
- new pkgAcqIndex(Owner, Target, ExpectedHash, MetaIndexParser);
+ new pkgAcqIndex(Owner, Target, ExpectedHashes, MetaIndexParser);
}
/*}}}*/
-void pkgAcqIndexMergeDiffs::Done(string Message,unsigned long long Size,string Md5Hash, /*{{{*/
+void pkgAcqIndexMergeDiffs::Done(string Message,unsigned long long Size,HashStringList const &Hashes, /*{{{*/
pkgAcquire::MethodConfig *Cnf)
{
if(Debug)
std::clog << "pkgAcqIndexMergeDiffs::Done(): " << Desc.URI << std::endl;
- Item::Done(Message,Size,Md5Hash,Cnf);
+ Item::Done(Message,Size,Hashes,Cnf);
string const FinalFile = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI);
@@ -890,7 +901,7 @@ void pkgAcqIndexMergeDiffs::Done(string Message,unsigned long long Size,string M
else if (State == StateApplyDiff)
{
// see if we really got the expected file
- if(!ExpectedHash.empty() && !ExpectedHash.VerifyFile(DestFile))
+ if(ExpectedHashes.usable() && !ExpectedHashes.VerifyFile(DestFile))
{
RenameOnError(HashSumMismatch);
return;
@@ -927,7 +938,7 @@ void pkgAcqIndexMergeDiffs::Done(string Message,unsigned long long Size,string M
instantiated to fetch the revision file */
pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner,
string URI,string URIDesc,string ShortDesc,
- HashString ExpectedHash, string comprExt)
+ HashStringList const &ExpectedHash, string comprExt)
: pkgAcqBaseIndex(Owner, NULL, ExpectedHash, NULL), RealURI(URI)
{
if(comprExt.empty() == true)
@@ -946,14 +957,15 @@ pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner,
Init(URI, URIDesc, ShortDesc);
}
pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner, IndexTarget const *Target,
- HashString const &ExpectedHash, indexRecords *MetaIndexParser)
+ HashStringList const &ExpectedHash,
+ indexRecords *MetaIndexParser)
: pkgAcqBaseIndex(Owner, Target, ExpectedHash, MetaIndexParser),
RealURI(Target->URI)
{
// autoselect the compression method
std::vector<std::string> types = APT::Configuration::getCompressionTypes();
CompressionExtension = "";
- if (ExpectedHash.empty() == false)
+ if (ExpectedHashes.usable())
{
for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
if (*t == "uncompressed" || MetaIndexParser->Exists(string(Target->MetaKey).append(".").append(*t)) == true)
@@ -1018,7 +1030,7 @@ void pkgAcqIndex::Init(string const &URI, string const &URIDesc, string const &S
// AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/
// ---------------------------------------------------------------------
/* The only header we use is the last-modified header. */
-string pkgAcqIndex::Custom600Headers()
+string pkgAcqIndex::Custom600Headers() const
{
string Final = _config->FindDir("Dir::State::lists");
Final += URItoFileName(RealURI);
@@ -1064,22 +1076,17 @@ 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 long Size,string Hash,
+void pkgAcqIndex::Done(string Message,unsigned long long Size,HashStringList const &Hashes,
pkgAcquire::MethodConfig *Cfg)
{
- Item::Done(Message,Size,Hash,Cfg);
+ Item::Done(Message,Size,Hashes,Cfg);
if (Decompression == true)
{
- if (_config->FindB("Debug::pkgAcquire::Auth", false))
- {
- std::cerr << std::endl << RealURI << ": Computed Hash: " << Hash;
- std::cerr << " Expected Hash: " << ExpectedHash.toStr() << std::endl;
- }
-
- if (!ExpectedHash.empty() && ExpectedHash.toStr() != Hash)
+ if (ExpectedHashes.usable() && ExpectedHashes != Hashes)
{
RenameOnError(HashSumMismatch);
+ printHashSumComparision(RealURI, ExpectedHashes, Hashes);
return;
}
@@ -1201,12 +1208,12 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,string Hash,
/* The Translation file is added to the queue */
pkgAcqIndexTrans::pkgAcqIndexTrans(pkgAcquire *Owner,
string URI,string URIDesc,string ShortDesc)
- : pkgAcqIndex(Owner, URI, URIDesc, ShortDesc, HashString(), "")
+ : pkgAcqIndex(Owner, URI, URIDesc, ShortDesc, HashStringList(), "")
{
}
-pkgAcqIndexTrans::pkgAcqIndexTrans(pkgAcquire *Owner, IndexTarget const *Target,
- HashString const &ExpectedHash, indexRecords *MetaIndexParser)
- : pkgAcqIndex(Owner, Target, ExpectedHash, MetaIndexParser)
+pkgAcqIndexTrans::pkgAcqIndexTrans(pkgAcquire *Owner, IndexTarget const * const Target,
+ HashStringList const &ExpectedHashes, indexRecords *MetaIndexParser)
+ : pkgAcqIndex(Owner, Target, ExpectedHashes, MetaIndexParser)
{
// load the filesize
indexRecords::checkSum *Record = MetaIndexParser->Lookup(string(Target->MetaKey));
@@ -1216,7 +1223,7 @@ pkgAcqIndexTrans::pkgAcqIndexTrans(pkgAcquire *Owner, IndexTarget const *Target,
/*}}}*/
// AcqIndexTrans::Custom600Headers - Insert custom request headers /*{{{*/
// ---------------------------------------------------------------------
-string pkgAcqIndexTrans::Custom600Headers()
+string pkgAcqIndexTrans::Custom600Headers() const
{
string Final = _config->FindDir("Dir::State::lists");
Final += URItoFileName(RealURI);
@@ -1260,7 +1267,7 @@ pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner, /*{{{*/
string MetaIndexShortDesc,
const vector<IndexTarget*>* IndexTargets,
indexRecords* MetaIndexParser) :
- Item(Owner), RealURI(URI), MetaIndexURI(MetaIndexURI),
+ Item(Owner, HashStringList()), RealURI(URI), MetaIndexURI(MetaIndexURI),
MetaIndexURIDesc(MetaIndexURIDesc), MetaIndexShortDesc(MetaIndexShortDesc),
MetaIndexParser(MetaIndexParser), IndexTargets(IndexTargets)
{
@@ -1313,7 +1320,7 @@ pkgAcqMetaSig::~pkgAcqMetaSig() /*{{{*/
// pkgAcqMetaSig::Custom600Headers - Insert custom request headers /*{{{*/
// ---------------------------------------------------------------------
/* The only header we use is the last-modified header. */
-string pkgAcqMetaSig::Custom600Headers()
+string pkgAcqMetaSig::Custom600Headers() const
{
struct stat Buf;
if (stat(LastGoodSig.c_str(),&Buf) != 0)
@@ -1322,10 +1329,10 @@ string pkgAcqMetaSig::Custom600Headers()
return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
}
-void pkgAcqMetaSig::Done(string Message,unsigned long long Size,string MD5,
+void pkgAcqMetaSig::Done(string Message,unsigned long long Size, HashStringList const &Hashes,
pkgAcquire::MethodConfig *Cfg)
{
- Item::Done(Message,Size,MD5,Cfg);
+ Item::Done(Message, Size, Hashes, Cfg);
string FileName = LookupTag(Message,"Filename");
if (FileName.empty() == true)
@@ -1405,9 +1412,9 @@ void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)/*{{{*/
pkgAcqMetaIndex::pkgAcqMetaIndex(pkgAcquire *Owner, /*{{{*/
string URI,string URIDesc,string ShortDesc,
string SigFile,
- const vector<struct IndexTarget*>* IndexTargets,
+ const vector<IndexTarget*>* IndexTargets,
indexRecords* MetaIndexParser) :
- Item(Owner), RealURI(URI), SigFile(SigFile), IndexTargets(IndexTargets),
+ Item(Owner, HashStringList()), RealURI(URI), SigFile(SigFile), IndexTargets(IndexTargets),
MetaIndexParser(MetaIndexParser), AuthPass(false), IMSHit(false)
{
DestFile = _config->FindDir("Dir::State::lists") + "partial/";
@@ -1428,7 +1435,7 @@ pkgAcqMetaIndex::pkgAcqMetaIndex(pkgAcquire *Owner, /*{{{*/
// pkgAcqMetaIndex::Custom600Headers - Insert custom request headers /*{{{*/
// ---------------------------------------------------------------------
/* The only header we use is the last-modified header. */
-string pkgAcqMetaIndex::Custom600Headers()
+string pkgAcqMetaIndex::Custom600Headers() const
{
string Final = _config->FindDir("Dir::State::lists");
Final += URItoFileName(RealURI);
@@ -1440,10 +1447,10 @@ string pkgAcqMetaIndex::Custom600Headers()
return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
}
/*}}}*/
-void pkgAcqMetaIndex::Done(string Message,unsigned long long Size,string Hash, /*{{{*/
+void pkgAcqMetaIndex::Done(string Message,unsigned long long Size,HashStringList const &Hashes, /*{{{*/
pkgAcquire::MethodConfig *Cfg)
{
- Item::Done(Message,Size,Hash,Cfg);
+ Item::Done(Message,Size,Hashes,Cfg);
// MetaIndexes are done in two passes: one to download the
// metaindex with an appropriate method, and a second to verify it
@@ -1614,12 +1621,12 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify) /*{{{*/
// at this point the real Items are loaded in the fetcher
ExpectedAdditionalItems = 0;
- for (vector <struct IndexTarget*>::const_iterator Target = IndexTargets->begin();
+ for (vector <IndexTarget*>::const_iterator Target = IndexTargets->begin();
Target != IndexTargets->end();
++Target)
{
- HashString ExpectedIndexHash;
- indexRecords::checkSum *Record = MetaIndexParser->Lookup((*Target)->MetaKey);
+ HashStringList ExpectedIndexHashes;
+ const indexRecords::checkSum *Record = MetaIndexParser->Lookup((*Target)->MetaKey);
bool compressedAvailable = false;
if (Record == NULL)
{
@@ -1642,14 +1649,16 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify) /*{{{*/
}
else
{
- ExpectedIndexHash = Record->Hash;
+ ExpectedIndexHashes = Record->Hashes;
if (_config->FindB("Debug::pkgAcquire::Auth", false))
{
- std::cerr << "Queueing: " << (*Target)->URI << std::endl;
- std::cerr << "Expected Hash: " << ExpectedIndexHash.toStr() << std::endl;
+ std::cerr << "Queueing: " << (*Target)->URI << std::endl
+ << "Expected Hash:" << std::endl;
+ for (HashStringList::const_iterator hs = ExpectedIndexHashes.begin(); hs != ExpectedIndexHashes.end(); ++hs)
+ std::cerr << "\t- " << hs->toStr() << std::endl;
std::cerr << "For: " << Record->MetaKeyFilename << std::endl;
}
- if (verify == true && ExpectedIndexHash.empty() == true && (*Target)->IsOptional() == false)
+ if (verify == true && ExpectedIndexHashes.empty() == true && (*Target)->IsOptional() == false)
{
Status = StatAuthError;
strprintf(ErrorText, _("Unable to find hash sum for '%s' in Release file"), (*Target)->MetaKey.c_str());
@@ -1661,14 +1670,14 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify) /*{{{*/
{
if ((*Target)->IsSubIndex() == true)
new pkgAcqSubIndex(Owner, (*Target)->URI, (*Target)->Description,
- (*Target)->ShortDesc, ExpectedIndexHash);
+ (*Target)->ShortDesc, ExpectedIndexHashes);
else if (transInRelease == false || Record != NULL || compressedAvailable == true)
{
if (_config->FindB("Acquire::PDiffs",true) == true && transInRelease == true &&
MetaIndexParser->Exists((*Target)->MetaKey + ".diff/Index") == true)
- new pkgAcqDiffIndex(Owner, *Target, ExpectedIndexHash, MetaIndexParser);
+ new pkgAcqDiffIndex(Owner, *Target, ExpectedIndexHashes, MetaIndexParser);
else
- new pkgAcqIndexTrans(Owner, *Target, ExpectedIndexHash, MetaIndexParser);
+ new pkgAcqIndexTrans(Owner, *Target, ExpectedIndexHashes, MetaIndexParser);
}
continue;
}
@@ -1679,9 +1688,9 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify) /*{{{*/
instead, but passing the required info to it is to much hassle */
if(_config->FindB("Acquire::PDiffs",true) == true && (verify == false ||
MetaIndexParser->Exists((*Target)->MetaKey + ".diff/Index") == true))
- new pkgAcqDiffIndex(Owner, *Target, ExpectedIndexHash, MetaIndexParser);
+ new pkgAcqDiffIndex(Owner, *Target, ExpectedIndexHashes, MetaIndexParser);
else
- new pkgAcqIndex(Owner, *Target, ExpectedIndexHash, MetaIndexParser);
+ new pkgAcqIndex(Owner, *Target, ExpectedIndexHashes, MetaIndexParser);
}
}
/*}}}*/
@@ -1834,7 +1843,7 @@ pkgAcqMetaClearSig::pkgAcqMetaClearSig(pkgAcquire *Owner, /*{{{*/
string const &URI, string const &URIDesc, string const &ShortDesc,
string const &MetaIndexURI, string const &MetaIndexURIDesc, string const &MetaIndexShortDesc,
string const &MetaSigURI, string const &MetaSigURIDesc, string const &MetaSigShortDesc,
- const vector<struct IndexTarget*>* IndexTargets,
+ const vector<IndexTarget*>* IndexTargets,
indexRecords* MetaIndexParser) :
pkgAcqMetaIndex(Owner, URI, URIDesc, ShortDesc, "", IndexTargets, MetaIndexParser),
MetaIndexURI(MetaIndexURI), MetaIndexURIDesc(MetaIndexURIDesc), MetaIndexShortDesc(MetaIndexShortDesc),
@@ -1870,7 +1879,7 @@ pkgAcqMetaClearSig::~pkgAcqMetaClearSig() /*{{{*/
// pkgAcqMetaClearSig::Custom600Headers - Insert custom request headers /*{{{*/
// ---------------------------------------------------------------------
// FIXME: this can go away once the InRelease file is used widely
-string pkgAcqMetaClearSig::Custom600Headers()
+string pkgAcqMetaClearSig::Custom600Headers() const
{
string Final = _config->FindDir("Dir::State::lists");
Final += URItoFileName(RealURI);
@@ -1919,7 +1928,7 @@ void pkgAcqMetaClearSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /*
pkgAcqArchive::pkgAcqArchive(pkgAcquire *Owner,pkgSourceList *Sources,
pkgRecords *Recs,pkgCache::VerIterator const &Version,
string &StoreFilename) :
- Item(Owner), Version(Version), Sources(Sources), Recs(Recs),
+ Item(Owner, HashStringList()), Version(Version), Sources(Sources), Recs(Recs),
StoreFilename(StoreFilename), Vf(Version.FileList()),
Trusted(false)
{
@@ -2004,7 +2013,6 @@ pkgAcqArchive::pkgAcqArchive(pkgAcquire *Owner,pkgSourceList *Sources,
checking later. */
bool pkgAcqArchive::QueueNext()
{
- string const ForceHash = _config->Find("Acquire::ForceHash");
for (; Vf.end() == false; ++Vf)
{
// Ignore not source sources
@@ -2025,31 +2033,10 @@ bool pkgAcqArchive::QueueNext()
pkgRecords::Parser &Parse = Recs->Lookup(Vf);
if (_error->PendingError() == true)
return false;
-
+
string PkgFile = Parse.FileName();
- if (ForceHash.empty() == false)
- {
- if(stringcasecmp(ForceHash, "sha512") == 0)
- ExpectedHash = HashString("SHA512", Parse.SHA512Hash());
- else if(stringcasecmp(ForceHash, "sha256") == 0)
- ExpectedHash = HashString("SHA256", Parse.SHA256Hash());
- else if (stringcasecmp(ForceHash, "sha1") == 0)
- ExpectedHash = HashString("SHA1", Parse.SHA1Hash());
- else
- ExpectedHash = HashString("MD5Sum", Parse.MD5Hash());
- }
- else
- {
- string Hash;
- if ((Hash = Parse.SHA512Hash()).empty() == false)
- ExpectedHash = HashString("SHA512", Hash);
- else if ((Hash = Parse.SHA256Hash()).empty() == false)
- ExpectedHash = HashString("SHA256", Hash);
- else if ((Hash = Parse.SHA1Hash()).empty() == false)
- ExpectedHash = HashString("SHA1", Hash);
- else
- ExpectedHash = HashString("MD5Sum", Parse.MD5Hash());
- }
+ ExpectedHashes = Parse.Hashes();
+
if (PkgFile.empty() == true)
return _error->Error(_("The package index files are corrupted. No Filename: "
"field for package %s."),
@@ -2136,10 +2123,10 @@ bool pkgAcqArchive::QueueNext()
// AcqArchive::Done - Finished fetching /*{{{*/
// ---------------------------------------------------------------------
/* */
-void pkgAcqArchive::Done(string Message,unsigned long long Size,string CalcHash,
+void pkgAcqArchive::Done(string Message,unsigned long long Size, HashStringList const &CalcHashes,
pkgAcquire::MethodConfig *Cfg)
{
- Item::Done(Message,Size,CalcHash,Cfg);
+ Item::Done(Message, Size, CalcHashes, Cfg);
// Check the size
if (Size != Version->Size)
@@ -2147,12 +2134,12 @@ void pkgAcqArchive::Done(string Message,unsigned long long Size,string CalcHash,
RenameOnError(SizeMismatch);
return;
}
-
- // Check the hash
+
// FIXME: could this empty() check impose *any* sort of security issue?
- if(ExpectedHash.empty() == false && ExpectedHash.toStr() != CalcHash)
+ if(ExpectedHashes.usable() && ExpectedHashes != CalcHashes)
{
RenameOnError(HashSumMismatch);
+ printHashSumComparision(DestFile, ExpectedHashes, CalcHashes);
return;
}
@@ -2224,7 +2211,7 @@ void pkgAcqArchive::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
/*}}}*/
// AcqArchive::IsTrusted - Determine whether this archive comes from a trusted source /*{{{*/
// ---------------------------------------------------------------------
-APT_PURE bool pkgAcqArchive::IsTrusted()
+APT_PURE bool pkgAcqArchive::IsTrusted() const
{
return Trusted;
}
@@ -2243,11 +2230,11 @@ void pkgAcqArchive::Finished()
// AcqFile::pkgAcqFile - Constructor /*{{{*/
// ---------------------------------------------------------------------
/* The file is added to the queue */
-pkgAcqFile::pkgAcqFile(pkgAcquire *Owner,string URI,string Hash,
+pkgAcqFile::pkgAcqFile(pkgAcquire *Owner,string URI, HashStringList const &Hashes,
unsigned long long Size,string Dsc,string ShortDesc,
const string &DestDir, const string &DestFilename,
bool IsIndexFile) :
- Item(Owner), ExpectedHash(Hash), IsIndexFile(IsIndexFile)
+ Item(Owner, Hashes), IsIndexFile(IsIndexFile)
{
Retries = _config->FindI("Acquire::Retries",0);
@@ -2284,15 +2271,16 @@ pkgAcqFile::pkgAcqFile(pkgAcquire *Owner,string URI,string Hash,
// AcqFile::Done - Item downloaded OK /*{{{*/
// ---------------------------------------------------------------------
/* */
-void pkgAcqFile::Done(string Message,unsigned long long Size,string CalcHash,
+void pkgAcqFile::Done(string Message,unsigned long long Size,HashStringList const &CalcHashes,
pkgAcquire::MethodConfig *Cnf)
{
- Item::Done(Message,Size,CalcHash,Cnf);
+ Item::Done(Message,Size,CalcHashes,Cnf);
// Check the hash
- if(!ExpectedHash.empty() && ExpectedHash.toStr() != CalcHash)
+ if(ExpectedHashes.usable() && ExpectedHashes != CalcHashes)
{
RenameOnError(HashSumMismatch);
+ printHashSumComparision(DestFile, ExpectedHashes, CalcHashes);
return;
}
@@ -2363,7 +2351,7 @@ void pkgAcqFile::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
// AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/
// ---------------------------------------------------------------------
/* The only header we use is the last-modified header. */
-string pkgAcqFile::Custom600Headers()
+string pkgAcqFile::Custom600Headers() const
{
if (IsIndexFile)
return "\nIndex-File: true";
diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h
index 35cd78afc..3d863874c 100644
--- a/apt-pkg/acquire-item.h
+++ b/apt-pkg/acquire-item.h
@@ -46,6 +46,7 @@
class indexRecords;
class pkgRecords;
class pkgSourceList;
+class IndexTarget;
/** \brief Represents the process by which a pkgAcquire object should {{{
* retrieve a file or a collection of files.
@@ -211,12 +212,12 @@ class pkgAcquire::Item : public WeakPointable
* \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 Hashes The HashSums of the object that was fetched.
* \param Cnf The method via which the object was fetched.
*
* \sa pkgAcqMethod
*/
- virtual void Done(std::string Message,unsigned long long Size,std::string Hash,
+ virtual void Done(std::string Message, unsigned long long Size, HashStringList const &Hashes,
pkgAcquire::MethodConfig *Cnf);
/** \brief Invoked when the worker starts to fetch this object.
@@ -238,34 +239,35 @@ class pkgAcquire::Item : public WeakPointable
* line, so they should (if nonempty) have a leading newline and
* no trailing newline.
*/
- virtual std::string Custom600Headers() {return std::string();};
+ virtual std::string Custom600Headers() const {return std::string();};
/** \brief A "descriptive" URI-like string.
*
* \return a URI that should be used to describe what is being fetched.
*/
- virtual std::string DescURI() = 0;
+ virtual std::string DescURI() const = 0;
/** \brief Short item description.
*
* \return a brief description of the object being fetched.
*/
- virtual std::string ShortDesc() {return DescURI();}
+ virtual std::string ShortDesc() const {return DescURI();}
/** \brief Invoked by the worker when the download is completely done. */
virtual void Finished() {};
- /** \brief HashSum
+ /** \brief HashSums
*
- * \return the HashSum of this object, if applicable; otherwise, an
- * empty string.
+ * \return the HashSums of this object, if applicable; otherwise, an
+ * empty list.
*/
- virtual std::string HashSum() {return std::string();};
+ HashStringList HashSums() const {return ExpectedHashes;};
+ std::string HashSum() const {HashStringList const hashes = HashSums(); HashString const * const hs = hashes.find(NULL); return hs != NULL ? hs->toStr() : ""; };
/** \return the acquire process with which this item is associated. */
- pkgAcquire *GetOwner() {return Owner;};
+ pkgAcquire *GetOwner() const {return Owner;};
/** \return \b true if this object is being fetched from a trusted source. */
- virtual bool IsTrusted() {return false;};
+ virtual bool IsTrusted() const {return false;};
// report mirror problems
/** \brief Report mirror problem
@@ -284,12 +286,10 @@ class pkgAcquire::Item : public WeakPointable
* 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.
+ * \param ExpectedHashes of the file represented by this item
*/
- Item(pkgAcquire *Owner);
+ Item(pkgAcquire *Owner, HashStringList const &ExpectedHashes);
/** \brief Remove this item from its owner's queue by invoking
* pkgAcquire::Remove.
@@ -309,6 +309,12 @@ class pkgAcquire::Item : public WeakPointable
* \param state respresenting the error we encountered
*/
bool RenameOnError(RenameOnErrorState const state);
+
+ /** \brief The HashSums of the item is supposed to have than done */
+ HashStringList ExpectedHashes;
+
+ /** \brief The item that is currently being downloaded. */
+ pkgAcquire::ItemDesc Desc;
};
/*}}}*/
/** \brief Information about an index patch (aka diff). */ /*{{{*/
@@ -335,20 +341,13 @@ class pkgAcqSubIndex : public pkgAcquire::Item
/** \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 Hash that this file should have after download
- */
- HashString ExpectedHash;
-
public:
// Specialized action members
virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
- virtual void Done(std::string Message,unsigned long long Size,std::string Md5Hash,
+ virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes,
pkgAcquire::MethodConfig *Cnf);
- virtual std::string DescURI() {return Desc.URI;};
- virtual std::string Custom600Headers();
+ virtual std::string DescURI() const {return Desc.URI;};
+ virtual std::string Custom600Headers() const;
virtual bool ParseIndex(std::string const &IndexFile);
/** \brief Create a new pkgAcqSubIndex.
@@ -361,10 +360,10 @@ class pkgAcqSubIndex : public pkgAcquire::Item
*
* \param ShortDesc A short description of the list file to download.
*
- * \param ExpectedHash The list file's MD5 signature.
+ * \param ExpectedHashes The list file's hashsums which are expected.
*/
pkgAcqSubIndex(pkgAcquire *Owner, std::string const &URI,std::string const &URIDesc,
- std::string const &ShortDesc, HashString const &ExpectedHash);
+ std::string const &ShortDesc, HashStringList const &ExpectedHashes);
};
/*}}}*/
@@ -379,16 +378,13 @@ class pkgAcqBaseIndex : public pkgAcquire::Item
const struct IndexTarget * Target;
indexRecords *MetaIndexParser;
- /** \brief The Hash that this file should have after download
- */
- HashString ExpectedHash;
-
pkgAcqBaseIndex(pkgAcquire *Owner,
struct IndexTarget const * const Target,
- HashString ExpectedHash,
+ HashStringList const &ExpectedHashes,
indexRecords *MetaIndexParser)
- : Item(Owner), Target(Target), MetaIndexParser(MetaIndexParser),
- ExpectedHash(ExpectedHash) {};
+ : Item(Owner, ExpectedHashes), Target(Target),
+ MetaIndexParser(MetaIndexParser) {};
+
};
/*}}}*/
/** \brief An item that is responsible for fetching an index file of {{{
@@ -406,9 +402,6 @@ class pkgAcqDiffIndex : public pkgAcqBaseIndex
/** \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).
*/
@@ -427,10 +420,10 @@ class pkgAcqDiffIndex : public pkgAcqBaseIndex
public:
// Specialized action members
virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
- virtual void Done(std::string Message,unsigned long long Size,std::string Md5Hash,
+ virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes,
pkgAcquire::MethodConfig *Cnf);
- virtual std::string DescURI() {return RealURI + "Index";};
- virtual std::string Custom600Headers();
+ virtual std::string DescURI() const {return RealURI + "Index";};
+ virtual std::string Custom600Headers() const;
/** \brief Parse the Index file for a set of Packages diffs.
*
@@ -455,11 +448,11 @@ class pkgAcqDiffIndex : public pkgAcqBaseIndex
*
* \param ShortDesc A short description of the list file to download.
*
- * \param ExpectedHash The list file's MD5 signature.
+ * \param ExpectedHashes The list file's hashsums which are expected.
*/
pkgAcqDiffIndex(pkgAcquire *Owner,
struct IndexTarget const * const Target,
- HashString ExpectedHash,
+ HashStringList const &ExpectedHashes,
indexRecords *MetaIndexParser);
};
/*}}}*/
@@ -483,11 +476,6 @@ class pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex
*/
bool Debug;
- /** \brief description of the item that is currently being
- * downloaded.
- */
- pkgAcquire::ItemDesc Desc;
-
/** \brief URI of the package index file that is being
* reconstructed.
*/
@@ -525,10 +513,9 @@ class pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex
* outright; its arguments are ignored.
*/
virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
-
- virtual void Done(std::string Message,unsigned long long Size,std::string Md5Hash,
- pkgAcquire::MethodConfig *Cnf);
- virtual std::string DescURI() {return RealURI + "Index";};
+ virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes,
+ pkgAcquire::MethodConfig *Cnf);
+ virtual std::string DescURI() const {return RealURI + "Index";};
/** \brief Create an index merge-diff item.
*
@@ -541,7 +528,7 @@ class pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex
*
* \param ShortDesc A brief description of this item.
*
- * \param ExpectedHash The expected md5sum of the completely
+ * \param ExpectedHashes The expected md5sum of the completely
* reconstructed package index file; the index file will be tested
* against this value when it is entirely reconstructed.
*
@@ -553,7 +540,7 @@ class pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex
*/
pkgAcqIndexMergeDiffs(pkgAcquire *Owner,
struct IndexTarget const * const Target,
- HashString ExpectedHash,
+ HashStringList const &ExpectedHash,
indexRecords *MetaIndexParser,
DiffInfo const &patch,
std::vector<pkgAcqIndexMergeDiffs*> const * const allPatches);
@@ -588,8 +575,8 @@ class pkgAcqIndexDiffs : public pkgAcqBaseIndex
/** \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.
+ * Dequeues the item and checks the resulting file's hashsums
+ * against ExpectedHashes 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.
*
@@ -605,11 +592,6 @@ class pkgAcqIndexDiffs : public pkgAcqBaseIndex
*/
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.
*/
@@ -656,9 +638,9 @@ class pkgAcqIndexDiffs : public pkgAcqBaseIndex
*/
virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
- virtual void Done(std::string Message,unsigned long long Size,std::string Md5Hash,
+ virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes,
pkgAcquire::MethodConfig *Cnf);
- virtual std::string DescURI() {return RealURI + "Index";};
+ virtual std::string DescURI() const {return RealURI + "Index";};
/** \brief Create an index diff item.
*
@@ -674,7 +656,7 @@ class pkgAcqIndexDiffs : public pkgAcqBaseIndex
*
* \param ShortDesc A brief description of this item.
*
- * \param ExpectedHash The expected md5sum of the completely
+ * \param ExpectedHashes The expected md5sum of the completely
* reconstructed package index file; the index file will be tested
* against this value when it is entirely reconstructed.
*
@@ -686,7 +668,7 @@ class pkgAcqIndexDiffs : public pkgAcqBaseIndex
*/
pkgAcqIndexDiffs(pkgAcquire *Owner,
struct IndexTarget const * const Target,
- HashString ExpectedHash,
+ HashStringList const &ExpectedHash,
indexRecords *MetaIndexParser,
std::string ServerSha1,
std::vector<DiffInfo> diffs=std::vector<DiffInfo>());
@@ -721,11 +703,6 @@ class pkgAcqIndex : public pkgAcqBaseIndex
// the downloaded file contains the expected tag
bool Verify;
- /** \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).
*/
@@ -740,11 +717,10 @@ class pkgAcqIndex : public pkgAcqBaseIndex
// Specialized action members
virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
- virtual void Done(std::string Message,unsigned long long Size,std::string Md5Hash,
+ virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes,
pkgAcquire::MethodConfig *Cnf);
- virtual std::string Custom600Headers();
- virtual std::string DescURI() {return Desc.URI;};
- virtual std::string HashSum() {return ExpectedHash.toStr(); };
+ virtual std::string Custom600Headers() const;
+ virtual std::string DescURI() const {return Desc.URI;};
/** \brief Create a pkgAcqIndex.
*
@@ -757,7 +733,7 @@ class pkgAcqIndex : public pkgAcqBaseIndex
*
* \param ShortDesc A brief description of this index file.
*
- * \param ExpectedHash The expected hashsum of this index file.
+ * \param ExpectedHashes The expected hashsum of this index file.
*
* \param compressExt The compression-related extension with which
* this index file should be downloaded, or "" to autodetect
@@ -766,11 +742,11 @@ class pkgAcqIndex : public pkgAcqBaseIndex
* fallback is ".gz" or none.
*/
pkgAcqIndex(pkgAcquire *Owner,std::string URI,std::string URIDesc,
- std::string ShortDesc, HashString ExpectedHash,
+ std::string ShortDesc, HashStringList const &ExpectedHashes,
std::string compressExt="");
pkgAcqIndex(pkgAcquire *Owner,
struct IndexTarget const * const Target,
- HashString const &ExpectedHash,
+ HashStringList const &ExpectedHash,
indexRecords *MetaIndexParser);
void Init(std::string const &URI, std::string const &URIDesc,
std::string const &ShortDesc);
@@ -788,7 +764,7 @@ class pkgAcqIndexTrans : public pkgAcqIndex
public:
virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
- virtual std::string Custom600Headers();
+ virtual std::string Custom600Headers() const;
/** \brief Create a pkgAcqIndexTrans.
*
@@ -803,8 +779,8 @@ class pkgAcqIndexTrans : public pkgAcqIndex
*/
pkgAcqIndexTrans(pkgAcquire *Owner,std::string URI,std::string URIDesc,
std::string ShortDesc);
- pkgAcqIndexTrans(pkgAcquire *Owner, struct IndexTarget const * const Target,
- HashString const &ExpectedHash, indexRecords *MetaIndexParser);
+ pkgAcqIndexTrans(pkgAcquire *Owner, IndexTarget const * const Target,
+ HashStringList const &ExpectedHashes, indexRecords *MetaIndexParser);
};
/*}}}*/
/** \brief Information about an index file. */ /*{{{*/
@@ -872,9 +848,6 @@ class pkgAcqMetaSig : public pkgAcquire::Item
/** \brief The last good signature file */
std::string LastGoodSig;
- /** \brief The fetch request that is currently being processed. */
- pkgAcquire::ItemDesc Desc;
-
/** \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.
@@ -902,21 +875,21 @@ class pkgAcqMetaSig : public pkgAcquire::Item
*
* \todo Why a list of pointers instead of a list of structs?
*/
- const std::vector<struct IndexTarget*>* IndexTargets;
+ const std::vector<IndexTarget*>* IndexTargets;
public:
// Specialized action members
virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
- virtual void Done(std::string Message,unsigned long long Size,std::string Md5Hash,
+ virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes,
pkgAcquire::MethodConfig *Cnf);
- virtual std::string Custom600Headers();
- virtual std::string DescURI() {return RealURI; };
+ virtual std::string Custom600Headers() const;
+ virtual std::string DescURI() const {return RealURI; };
/** \brief Create a new pkgAcqMetaSig. */
pkgAcqMetaSig(pkgAcquire *Owner,std::string URI,std::string URIDesc, std::string ShortDesc,
std::string MetaIndexURI, std::string MetaIndexURIDesc, std::string MetaIndexShortDesc,
- const std::vector<struct IndexTarget*>* IndexTargets,
+ const std::vector<IndexTarget*>* IndexTargets,
indexRecords* MetaIndexParser);
virtual ~pkgAcqMetaSig();
};
@@ -934,9 +907,6 @@ class pkgAcqMetaSig : public pkgAcquire::Item
class pkgAcqMetaIndex : public pkgAcquire::Item
{
protected:
- /** \brief The fetch command that is currently being processed. */
- pkgAcquire::ItemDesc Desc;
-
/** \brief The URI that is actually being downloaded; never
* modified by pkgAcqMetaIndex.
*/
@@ -950,7 +920,7 @@ class pkgAcqMetaIndex : public pkgAcquire::Item
std::string SigFile;
/** \brief The index files to download. */
- const std::vector<struct IndexTarget*>* IndexTargets;
+ const std::vector<IndexTarget*>* IndexTargets;
/** \brief The parser for the meta-index file. */
indexRecords* MetaIndexParser;
@@ -1004,16 +974,16 @@ class pkgAcqMetaIndex : public pkgAcquire::Item
// Specialized action members
virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
- virtual void Done(std::string Message,unsigned long long Size, std::string Hash,
+ virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes,
pkgAcquire::MethodConfig *Cnf);
- virtual std::string Custom600Headers();
- virtual std::string DescURI() {return RealURI; };
+ virtual std::string Custom600Headers() const;
+ virtual std::string DescURI() const {return RealURI; };
/** \brief Create a new pkgAcqMetaIndex. */
pkgAcqMetaIndex(pkgAcquire *Owner,
std::string URI,std::string URIDesc, std::string ShortDesc,
std::string SigFile,
- const std::vector<struct IndexTarget*>* IndexTargets,
+ const std::vector<IndexTarget*>* IndexTargets,
indexRecords* MetaIndexParser);
};
/*}}}*/
@@ -1040,14 +1010,14 @@ class pkgAcqMetaClearSig : public pkgAcqMetaIndex
public:
void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
- virtual std::string Custom600Headers();
+ virtual std::string Custom600Headers() const;
/** \brief Create a new pkgAcqMetaClearSig. */
pkgAcqMetaClearSig(pkgAcquire *Owner,
std::string const &URI, std::string const &URIDesc, std::string const &ShortDesc,
std::string const &MetaIndexURI, std::string const &MetaIndexURIDesc, std::string const &MetaIndexShortDesc,
std::string const &MetaSigURI, std::string const &MetaSigURIDesc, std::string const &MetaSigShortDesc,
- const std::vector<struct IndexTarget*>* IndexTargets,
+ const std::vector<IndexTarget*>* IndexTargets,
indexRecords* MetaIndexParser);
virtual ~pkgAcqMetaClearSig();
};
@@ -1063,9 +1033,6 @@ class pkgAcqArchive : public pkgAcquire::Item
/** \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.
*/
@@ -1076,9 +1043,6 @@ class pkgAcqArchive : public pkgAcquire::Item
*/
pkgRecords *Recs;
- /** \brief The hashsum of this package. */
- HashString ExpectedHash;
-
/** \brief A location in which the actual filename of the package
* should be stored.
*/
@@ -1105,13 +1069,12 @@ class pkgAcqArchive : public pkgAcquire::Item
public:
virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
- virtual void Done(std::string Message,unsigned long long Size,std::string Hash,
+ virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes,
pkgAcquire::MethodConfig *Cnf);
- virtual std::string DescURI() {return Desc.URI;};
- virtual std::string ShortDesc() {return Desc.ShortDesc;};
+ virtual std::string DescURI() const {return Desc.URI;};
+ virtual std::string ShortDesc() const {return Desc.ShortDesc;};
virtual void Finished();
- virtual std::string HashSum() {return ExpectedHash.toStr(); };
- virtual bool IsTrusted();
+ virtual bool IsTrusted() const;
/** \brief Create a new pkgAcqArchive.
*
@@ -1144,12 +1107,6 @@ class pkgAcqArchive : public pkgAcquire::Item
*/
class pkgAcqFile : public pkgAcquire::Item
{
- /** \brief The currently active download process. */
- pkgAcquire::ItemDesc Desc;
-
- /** \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.
*/
@@ -1162,11 +1119,10 @@ class pkgAcqFile : public pkgAcquire::Item
// Specialized action members
virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
- virtual void Done(std::string Message,unsigned long long Size,std::string CalcHash,
+ virtual void Done(std::string Message,unsigned long long Size, HashStringList const &CalcHashes,
pkgAcquire::MethodConfig *Cnf);
- virtual std::string DescURI() {return Desc.URI;};
- virtual std::string HashSum() {return ExpectedHash.toStr(); };
- virtual std::string Custom600Headers();
+ virtual std::string DescURI() const {return Desc.URI;};
+ virtual std::string Custom600Headers() const;
/** \brief Create a new pkgAcqFile object.
*
@@ -1175,8 +1131,8 @@ class pkgAcqFile : public pkgAcquire::Item
*
* \param URI The URI to download.
*
- * \param Hash The hashsum of the file to download, if it is known;
- * otherwise "".
+ * \param Hashes The hashsums of the file to download, if they are known;
+ * otherwise empty list.
*
* \param Size The size of the file to download, if it is known;
* otherwise 0.
@@ -1199,7 +1155,7 @@ class pkgAcqFile : public pkgAcquire::Item
* is the absolute name to which the file should be downloaded.
*/
- pkgAcqFile(pkgAcquire *Owner, std::string URI, std::string Hash, unsigned long long Size,
+ pkgAcqFile(pkgAcquire *Owner, std::string URI, HashStringList const &Hashes, unsigned long long Size,
std::string Desc, std::string ShortDesc,
const std::string &DestDir="", const std::string &DestFilename="",
bool IsIndexFile=false);
diff --git a/apt-pkg/acquire-method.cc b/apt-pkg/acquire-method.cc
index 746c553f1..e4a937d1d 100644
--- a/apt-pkg/acquire-method.cc
+++ b/apt-pkg/acquire-method.cc
@@ -147,6 +147,16 @@ void pkgAcqMethod::URIStart(FetchResult &Res)
// AcqMethod::URIDone - A URI is finished /*{{{*/
// ---------------------------------------------------------------------
/* */
+static void printHashStringList(HashStringList const * const list)
+{
+ for (HashStringList::const_iterator hash = list->begin(); hash != list->end(); ++hash)
+ {
+ // very old compatibility name for MD5Sum
+ if (hash->HashType() == "MD5Sum")
+ std::cout << "MD5-Hash: " << hash->HashValue() << "\n";
+ std::cout << hash->HashType() << "-Hash: " << hash->HashValue() << "\n";
+ }
+}
void pkgAcqMethod::URIDone(FetchResult &Res, FetchResult *Alt)
{
if (Queue == 0)
@@ -164,15 +174,8 @@ void pkgAcqMethod::URIDone(FetchResult &Res, FetchResult *Alt)
if (Res.LastModified != 0)
std::cout << "Last-Modified: " << TimeRFC1123(Res.LastModified) << "\n";
- if (Res.MD5Sum.empty() == false)
- std::cout << "MD5-Hash: " << Res.MD5Sum << "\n"
- << "MD5Sum-Hash: " << Res.MD5Sum << "\n";
- if (Res.SHA1Sum.empty() == false)
- std::cout << "SHA1-Hash: " << Res.SHA1Sum << "\n";
- if (Res.SHA256Sum.empty() == false)
- std::cout << "SHA256-Hash: " << Res.SHA256Sum << "\n";
- if (Res.SHA512Sum.empty() == false)
- std::cout << "SHA512-Hash: " << Res.SHA512Sum << "\n";
+ printHashStringList(&Res.Hashes);
+
if (UsedMirror.empty() == false)
std::cout << "UsedMirror: " << UsedMirror << "\n";
if (Res.GPGVOutput.empty() == false)
@@ -200,15 +203,8 @@ void pkgAcqMethod::URIDone(FetchResult &Res, FetchResult *Alt)
if (Alt->LastModified != 0)
std::cout << "Alt-Last-Modified: " << TimeRFC1123(Alt->LastModified) << "\n";
- if (Alt->MD5Sum.empty() == false)
- std::cout << "Alt-MD5-Hash: " << Alt->MD5Sum << "\n";
- if (Alt->SHA1Sum.empty() == false)
- std::cout << "Alt-SHA1-Hash: " << Alt->SHA1Sum << "\n";
- if (Alt->SHA256Sum.empty() == false)
- std::cout << "Alt-SHA256-Hash: " << Alt->SHA256Sum << "\n";
- if (Alt->SHA512Sum.empty() == false)
- std::cout << "Alt-SHA512-Hash: " << Alt->SHA512Sum << "\n";
-
+ printHashStringList(&Alt->Hashes);
+
if (Alt->IMSHit == true)
std::cout << "Alt-IMS-Hit: true\n";
}
@@ -355,6 +351,15 @@ int pkgAcqMethod::Run(bool Single)
Tmp->LastModified = 0;
Tmp->IndexFile = StringToBool(LookupTag(Message,"Index-File"),false);
Tmp->FailIgnore = StringToBool(LookupTag(Message,"Fail-Ignore"),false);
+ Tmp->ExpectedHashes = HashStringList();
+ for (char const * const * t = HashString::SupportedHashes(); *t != NULL; ++t)
+ {
+ std::string tag = "Expected-";
+ tag.append(*t);
+ std::string const hash = LookupTag(Message, tag.c_str());
+ if (hash.empty() == false)
+ Tmp->ExpectedHashes.push_back(HashString(*t, hash));
+ }
Tmp->Next = 0;
// Append it to the list
@@ -442,12 +447,9 @@ pkgAcqMethod::FetchResult::FetchResult() : LastModified(0),
// ---------------------------------------------------------------------
/* This hides the number of hashes we are supporting from the caller.
It just deals with the hash class. */
-void pkgAcqMethod::FetchResult::TakeHashes(Hashes &Hash)
+void pkgAcqMethod::FetchResult::TakeHashes(class Hashes &Hash)
{
- MD5Sum = Hash.MD5.Result();
- SHA1Sum = Hash.SHA1.Result();
- SHA256Sum = Hash.SHA256.Result();
- SHA512Sum = Hash.SHA512.Result();
+ Hashes = Hash.GetHashStringList();
}
/*}}}*/
void pkgAcqMethod::Dequeue() { /*{{{*/
diff --git a/apt-pkg/acquire-method.h b/apt-pkg/acquire-method.h
index 221ccf273..cbf79f860 100644
--- a/apt-pkg/acquire-method.h
+++ b/apt-pkg/acquire-method.h
@@ -20,6 +20,7 @@
#ifndef PKGLIB_ACQUIRE_METHOD_H
#define PKGLIB_ACQUIRE_METHOD_H
+#include <apt-pkg/hashes.h>
#include <apt-pkg/macros.h>
#include <stdarg.h>
@@ -33,7 +34,6 @@
#include <apt-pkg/strutl.h>
#endif
-class Hashes;
class pkgAcqMethod
{
protected:
@@ -47,14 +47,12 @@ class pkgAcqMethod
time_t LastModified;
bool IndexFile;
bool FailIgnore;
+ HashStringList ExpectedHashes;
};
struct FetchResult
{
- std::string MD5Sum;
- std::string SHA1Sum;
- std::string SHA256Sum;
- std::string SHA512Sum;
+ HashStringList Hashes;
std::vector<std::string> GPGVOutput;
time_t LastModified;
bool IMSHit;
@@ -62,7 +60,7 @@ class pkgAcqMethod
unsigned long long Size;
unsigned long long ResumePoint;
- void TakeHashes(Hashes &Hash);
+ void TakeHashes(class Hashes &Hash);
FetchResult();
};
diff --git a/apt-pkg/acquire-worker.cc b/apt-pkg/acquire-worker.cc
index 047a655ce..54be8e99f 100644
--- a/apt-pkg/acquire-worker.cc
+++ b/apt-pkg/acquire-worker.cc
@@ -326,25 +326,30 @@ bool pkgAcquire::Worker::RunMessages()
Owner->DestFile.c_str(), LookupTag(Message,"Size","0").c_str(),TotalSize);
// see if there is a hash to verify
- string RecivedHash;
- HashString expectedHash(Owner->HashSum());
- if(!expectedHash.empty())
+ HashStringList RecivedHashes;
+ HashStringList expectedHashes = Owner->HashSums();
+ for (HashStringList::const_iterator hs = expectedHashes.begin(); hs != expectedHashes.end(); ++hs)
{
- 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;
- }
+ std::string const tagname = hs->HashType() + "-Hash";
+ std::string const hashsum = LookupTag(Message, tagname.c_str());
+ if (hashsum.empty() == false)
+ RecivedHashes.push_back(HashString(hs->HashType(), hashsum));
+ }
+
+ if(_config->FindB("Debug::pkgAcquire::Auth", false) == true)
+ {
+ std::clog << "201 URI Done: " << Owner->DescURI() << endl
+ << "RecivedHash:" << endl;
+ for (HashStringList::const_iterator hs = RecivedHashes.begin(); hs != RecivedHashes.end(); ++hs)
+ std::clog << "\t- " << hs->toStr() << std::endl;
+ std::clog << "ExpectedHash:" << endl;
+ for (HashStringList::const_iterator hs = expectedHashes.begin(); hs != expectedHashes.end(); ++hs)
+ std::clog << "\t- " << hs->toStr() << std::endl;
+ std::clog << endl;
}
- Owner->Done(Message, ServerSize, RecivedHash.c_str(), Config);
+ Owner->Done(Message, ServerSize, RecivedHashes, Config);
ItemDone();
-
+
// Log that we are done
if (Log != 0)
{
@@ -525,6 +530,9 @@ bool pkgAcquire::Worker::QueueItem(pkgAcquire::Queue::QItem *Item)
Message.reserve(300);
Message += "URI: " + Item->URI;
Message += "\nFilename: " + Item->Owner->DestFile;
+ HashStringList const hsl = Item->Owner->HashSums();
+ for (HashStringList::const_iterator hs = hsl.begin(); hs != hsl.end(); ++hs)
+ Message += "\nExpected-" + hs->HashType() + ": " + hs->HashValue();
Message += Item->Owner->Custom600Headers();
Message += "\n\n";
diff --git a/apt-pkg/aptconfiguration.cc b/apt-pkg/aptconfiguration.cc
index 9982759c6..94b6bc246 100644
--- a/apt-pkg/aptconfiguration.cc
+++ b/apt-pkg/aptconfiguration.cc
@@ -540,7 +540,7 @@ std::string const Configuration::getBuildProfilesString() {
return "";
std::vector<std::string>::const_iterator p = profiles.begin();
std::string list = *p;
- for (; p != profiles.end(); ++p)
+ for (++p; p != profiles.end(); ++p)
list.append(",").append(*p);
return list;
}
diff --git a/apt-pkg/contrib/hashes.cc b/apt-pkg/contrib/hashes.cc
index 15f83615d..199e395f6 100644
--- a/apt-pkg/contrib/hashes.cc
+++ b/apt-pkg/contrib/hashes.cc
@@ -27,7 +27,7 @@
#include <iostream>
/*}}}*/
-const char* HashString::_SupportedHashes[] =
+const char * HashString::_SupportedHashes[] =
{
"SHA512", "SHA256", "SHA1", "MD5Sum", NULL
};
@@ -42,11 +42,16 @@ HashString::HashString(std::string Type, std::string Hash) : Type(Type), Hash(Ha
HashString::HashString(std::string StringedHash) /*{{{*/
{
- // legacy: md5sum without "MD5Sum:" prefix
- if (StringedHash.find(":") == std::string::npos && StringedHash.size() == 32)
+ if (StringedHash.find(":") == std::string::npos)
{
- Type = "MD5Sum";
- Hash = StringedHash;
+ // legacy: md5sum without "MD5Sum:" prefix
+ if (StringedHash.size() == 32)
+ {
+ Type = "MD5Sum";
+ Hash = StringedHash;
+ }
+ if(_config->FindB("Debug::Hashes",false) == true)
+ std::clog << "HashString(string): invalid StringedHash " << StringedHash << std::endl;
return;
}
std::string::size_type pos = StringedHash.find(":");
@@ -82,25 +87,25 @@ std::string HashString::GetHashForFile(std::string filename) const /*{{{*/
std::string fileHash;
FileFd Fd(filename, FileFd::ReadOnly);
- if(Type == "MD5Sum")
+ if(strcasecmp(Type.c_str(), "MD5Sum") == 0)
{
MD5Summation MD5;
MD5.AddFD(Fd);
fileHash = (std::string)MD5.Result();
}
- else if (Type == "SHA1")
+ else if (strcasecmp(Type.c_str(), "SHA1") == 0)
{
SHA1Summation SHA1;
SHA1.AddFD(Fd);
fileHash = (std::string)SHA1.Result();
}
- else if (Type == "SHA256")
+ else if (strcasecmp(Type.c_str(), "SHA256") == 0)
{
SHA256Summation SHA256;
SHA256.AddFD(Fd);
fileHash = (std::string)SHA256.Result();
}
- else if (Type == "SHA512")
+ else if (strcasecmp(Type.c_str(), "SHA512") == 0)
{
SHA512Summation SHA512;
SHA512.AddFD(Fd);
@@ -111,26 +116,147 @@ std::string HashString::GetHashForFile(std::string filename) const /*{{{*/
return fileHash;
}
/*}}}*/
-const char** HashString::SupportedHashes()
+const char** HashString::SupportedHashes() /*{{{*/
{
return _SupportedHashes;
}
-
-APT_PURE bool HashString::empty() const
+ /*}}}*/
+APT_PURE bool HashString::empty() const /*{{{*/
{
return (Type.empty() || Hash.empty());
}
+ /*}}}*/
+std::string HashString::toStr() const /*{{{*/
+{
+ return Type + ":" + Hash;
+}
+ /*}}}*/
+APT_PURE bool HashString::operator==(HashString const &other) const /*{{{*/
+{
+ return (strcasecmp(Type.c_str(), other.Type.c_str()) == 0 && Hash == other.Hash);
+}
+APT_PURE bool HashString::operator!=(HashString const &other) const
+{
+ return !(*this == other);
+}
+ /*}}}*/
+
+bool HashStringList::usable() const /*{{{*/
+{
+ if (empty() == true)
+ return false;
+ std::string const forcedType = _config->Find("Acquire::ForceHash", "");
+ if (forcedType.empty() == true)
+ return true;
+ return find(forcedType) != NULL;
+}
+ /*}}}*/
+HashString const * HashStringList::find(char const * const type) const /*{{{*/
+{
+ if (type == NULL || type[0] == '\0')
+ {
+ std::string const forcedType = _config->Find("Acquire::ForceHash", "");
+ if (forcedType.empty() == false)
+ return find(forcedType.c_str());
+ for (char const * const * t = HashString::SupportedHashes(); *t != NULL; ++t)
+ for (std::vector<HashString>::const_iterator hs = list.begin(); hs != list.end(); ++hs)
+ if (strcasecmp(hs->HashType().c_str(), *t) == 0)
+ return &*hs;
+ return NULL;
+ }
+ for (std::vector<HashString>::const_iterator hs = list.begin(); hs != list.end(); ++hs)
+ if (strcasecmp(hs->HashType().c_str(), type) == 0)
+ return &*hs;
+ return NULL;
+}
+ /*}}}*/
+bool HashStringList::supported(char const * const type) /*{{{*/
+{
+ for (char const * const * t = HashString::SupportedHashes(); *t != NULL; ++t)
+ if (strcasecmp(*t, type) == 0)
+ return true;
+ return false;
+}
+ /*}}}*/
+bool HashStringList::push_back(const HashString &hashString) /*{{{*/
+{
+ if (hashString.HashType().empty() == true ||
+ hashString.HashValue().empty() == true ||
+ supported(hashString.HashType().c_str()) == false)
+ return false;
+
+ // ensure that each type is added only once
+ HashString const * const hs = find(hashString.HashType().c_str());
+ if (hs != NULL)
+ return *hs == hashString;
-std::string HashString::toStr() const
+ list.push_back(hashString);
+ return true;
+}
+ /*}}}*/
+bool HashStringList::VerifyFile(std::string filename) const /*{{{*/
{
- return Type + std::string(":") + Hash;
+ if (list.empty() == true)
+ return false;
+ HashString const * const hs = find(NULL);
+ if (hs == NULL || hs->VerifyFile(filename) == false)
+ return false;
+ return true;
}
+ /*}}}*/
+bool HashStringList::operator==(HashStringList const &other) const /*{{{*/
+{
+ std::string const forcedType = _config->Find("Acquire::ForceHash", "");
+ if (forcedType.empty() == false)
+ {
+ HashString const * const hs = other.find(forcedType);
+ HashString const * const ohs = other.find(forcedType);
+ if (hs == NULL || ohs == NULL)
+ return false;
+ return hs == ohs;
+ }
+ short matches = 0;
+ for (const_iterator hs = begin(); hs != end(); ++hs)
+ {
+ HashString const * const ohs = other.find(hs->HashType());
+ if (ohs == NULL)
+ continue;
+ if (*hs != *ohs)
+ return false;
+ ++matches;
+ }
+ if (matches == 0)
+ return false;
+ return true;
+}
+bool HashStringList::operator!=(HashStringList const &other) const
+{
+ return !(*this == other);
+}
+ /*}}}*/
-// Hashes::AddFD - Add the contents of the FD /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool Hashes::AddFD(int const Fd,unsigned long long Size, bool const addMD5,
- bool const addSHA1, bool const addSHA256, bool const addSHA512)
+// Hashes::Add* - Add the contents of data or FD /*{{{*/
+bool Hashes::Add(const unsigned char * const Data,unsigned long long const Size, unsigned int const Hashes)
+{
+ bool Res = true;
+#if __GNUC__ >= 4
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+ if ((Hashes & MD5SUM) == MD5SUM)
+ Res &= MD5.Add(Data, Size);
+ if ((Hashes & SHA1SUM) == SHA1SUM)
+ Res &= SHA1.Add(Data, Size);
+ if ((Hashes & SHA256SUM) == SHA256SUM)
+ Res &= SHA256.Add(Data, Size);
+ if ((Hashes & SHA512SUM) == SHA512SUM)
+ Res &= SHA512.Add(Data, Size);
+#if __GNUC__ >= 4
+ #pragma GCC diagnostic pop
+#endif
+ return Res;
+}
+bool Hashes::AddFD(int const Fd,unsigned long long Size, unsigned int const Hashes)
{
unsigned char Buf[64*64];
bool const ToEOF = (Size == UntilEOF);
@@ -144,19 +270,12 @@ bool Hashes::AddFD(int const Fd,unsigned long long Size, bool const addMD5,
if (ToEOF && Res == 0) // EOF
break;
Size -= Res;
- if (addMD5 == true)
- MD5.Add(Buf,Res);
- if (addSHA1 == true)
- SHA1.Add(Buf,Res);
- if (addSHA256 == true)
- SHA256.Add(Buf,Res);
- if (addSHA512 == true)
- SHA512.Add(Buf,Res);
+ if (Add(Buf, Res, Hashes) == false)
+ return false;
}
return true;
}
-bool Hashes::AddFD(FileFd &Fd,unsigned long long Size, bool const addMD5,
- bool const addSHA1, bool const addSHA256, bool const addSHA512)
+bool Hashes::AddFD(FileFd &Fd,unsigned long long Size, unsigned int const Hashes)
{
unsigned char Buf[64*64];
bool const ToEOF = (Size == 0);
@@ -175,15 +294,35 @@ bool Hashes::AddFD(FileFd &Fd,unsigned long long Size, bool const addMD5,
else if (a == 0) // EOF
break;
Size -= a;
- if (addMD5 == true)
- MD5.Add(Buf, a);
- if (addSHA1 == true)
- SHA1.Add(Buf, a);
- if (addSHA256 == true)
- SHA256.Add(Buf, a);
- if (addSHA512 == true)
- SHA512.Add(Buf, a);
+ if (Add(Buf, a, Hashes) == false)
+ return false;
}
return true;
}
/*}}}*/
+HashStringList Hashes::GetHashStringList()
+{
+ HashStringList hashes;
+#if __GNUC__ >= 4
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+ hashes.push_back(HashString("MD5Sum", MD5.Result().Value()));
+ hashes.push_back(HashString("SHA1", SHA1.Result().Value()));
+ hashes.push_back(HashString("SHA256", SHA256.Result().Value()));
+ hashes.push_back(HashString("SHA512", SHA512.Result().Value()));
+#if __GNUC__ >= 4
+ #pragma GCC diagnostic pop
+#endif
+ return hashes;
+}
+#if __GNUC__ >= 4
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+ #pragma GCC diagnostic ignored "-Wsuggest-attribute=const"
+#endif
+Hashes::Hashes() {}
+Hashes::~Hashes() {}
+#if __GNUC__ >= 4
+ #pragma GCC diagnostic pop
+#endif
diff --git a/apt-pkg/contrib/hashes.h b/apt-pkg/contrib/hashes.h
index 7a62f8a8f..caeba006d 100644
--- a/apt-pkg/contrib/hashes.h
+++ b/apt-pkg/contrib/hashes.h
@@ -17,6 +17,7 @@
#include <apt-pkg/md5.h>
#include <apt-pkg/sha1.h>
#include <apt-pkg/sha2.h>
+#include <apt-pkg/macros.h>
#include <cstring>
#include <string>
@@ -41,7 +42,7 @@ class HashString
protected:
std::string Type;
std::string Hash;
- static const char* _SupportedHashes[10];
+ static const char * _SupportedHashes[10];
// internal helper
std::string GetHashForFile(std::string filename) const;
@@ -52,7 +53,8 @@ class HashString
HashString();
// get hash type used
- std::string HashType() { return Type; };
+ std::string HashType() const { return Type; };
+ std::string HashValue() const { return Hash; };
// verify the given filename against the currently loaded hash
bool VerifyFile(std::string filename) const;
@@ -64,37 +66,160 @@ class HashString
// helper
std::string toStr() const; // convert to str as "type:hash"
bool empty() const;
+ bool operator==(HashString const &other) const;
+ bool operator!=(HashString const &other) const;
// return the list of hashes we support
static APT_CONST const char** SupportedHashes();
};
+class HashStringList
+{
+ public:
+ /** find best hash if no specific one is requested
+ *
+ * @param type of the checksum to return, can be \b NULL
+ * @return If type is \b NULL (or the empty string) it will
+ * return the 'best' hash; otherwise the hash which was
+ * specifically requested. If no hash is found \b NULL will be returned.
+ */
+ HashString const * find(char const * const type) const;
+ HashString const * find(std::string const &type) const { return find(type.c_str()); }
+ /** check if the given hash type is supported
+ *
+ * @param type to check
+ * @return true if supported, otherwise false
+ */
+ static APT_PURE bool supported(char const * const type);
+ /** add the given #HashString to the list
+ *
+ * @param hashString to add
+ * @return true if the hash is added because it is supported and
+ * not already a different hash of the same type included, otherwise false
+ */
+ bool push_back(const HashString &hashString);
+ /** @return size of the list of HashStrings */
+ size_t size() const { return list.size(); }
+
+ /** take the 'best' hash and verify file with it
+ *
+ * @param filename to verify
+ * @return true if the file matches the hashsum, otherwise false
+ */
+ bool VerifyFile(std::string filename) const;
+
+ /** is the list empty ?
+ *
+ * @return \b true if the list is empty, otherwise \b false
+ */
+ bool empty() const { return list.empty(); }
+
+ /** has the list at least one good entry
+ *
+ * similar to #empty, but handles forced hashes.
+ *
+ * @return if no hash is forced, same result as #empty,
+ * if one is forced \b true if this has is available, \b false otherwise
+ */
+ bool usable() const;
+
+ typedef std::vector<HashString>::const_iterator const_iterator;
+
+ /** iterator to the first element */
+ const_iterator begin() const { return list.begin(); }
+
+ /** iterator to the end element */
+ const_iterator end() const { return list.end(); }
+
+ /** start fresh with a clear list */
+ void clear() { list.clear(); }
+
+ /** compare two HashStringList for similarity.
+ *
+ * Two lists are similar if at least one hashtype is in both lists
+ * and the hashsum matches. All hashes are checked by default,
+ * if one doesn't match false is returned regardless of how many
+ * matched before. If a hash is forced, only this hash is compared,
+ * all others are ignored.
+ */
+ bool operator==(HashStringList const &other) const;
+ bool operator!=(HashStringList const &other) const;
+
+ HashStringList() {}
+
+ // simplifying API-compatibility constructors
+ HashStringList(std::string const &hash) {
+ if (hash.empty() == false)
+ list.push_back(HashString(hash));
+ }
+ HashStringList(char const * const hash) {
+ if (hash != NULL && hash[0] != '\0')
+ list.push_back(HashString(hash));
+ }
+
+ private:
+ std::vector<HashString> list;
+};
+
class Hashes
{
+ /** \brief dpointer placeholder */
+ void *d;
+
public:
+ /* those will disappear in the future as it is hard to add new ones this way.
+ * Use Add* to build the results and get them via GetHashStringList() instead */
+ APT_DEPRECATED MD5Summation MD5;
+ APT_DEPRECATED SHA1Summation SHA1;
+ APT_DEPRECATED SHA256Summation SHA256;
+ APT_DEPRECATED SHA512Summation SHA512;
- MD5Summation MD5;
- SHA1Summation SHA1;
- SHA256Summation SHA256;
- SHA512Summation SHA512;
-
static const int UntilEOF = 0;
- inline bool Add(const unsigned char *Data,unsigned long long Size)
+ bool Add(const unsigned char * const Data, unsigned long long const Size, unsigned int const Hashes = ~0);
+ inline bool Add(const char * const Data)
+ {return Add((unsigned char const * const)Data,strlen(Data));};
+ inline bool Add(const unsigned char * const Beg,const unsigned char * const End)
+ {return Add(Beg,End-Beg);};
+
+ enum SupportedHashes { MD5SUM = (1 << 0), SHA1SUM = (1 << 1), SHA256SUM = (1 << 2),
+ SHA512SUM = (1 << 3) };
+ bool AddFD(int const Fd,unsigned long long Size = 0, unsigned int const Hashes = ~0);
+ bool AddFD(FileFd &Fd,unsigned long long Size = 0, unsigned int const Hashes = ~0);
+
+ HashStringList GetHashStringList();
+
+#if __GNUC__ >= 4
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+ Hashes();
+ virtual ~Hashes();
+#if __GNUC__ >= 4
+ #pragma GCC diagnostic pop
+#endif
+
+ private:
+ APT_HIDDEN APT_CONST inline unsigned int boolsToFlag(bool const addMD5, bool const addSHA1, bool const addSHA256, bool const addSHA512)
{
- return MD5.Add(Data,Size) && SHA1.Add(Data,Size) && SHA256.Add(Data,Size) && SHA512.Add(Data,Size);
+ unsigned int Hashes = ~0;
+ if (addMD5 == false) Hashes &= ~MD5SUM;
+ if (addSHA1 == false) Hashes &= ~SHA1SUM;
+ if (addSHA256 == false) Hashes &= ~SHA256SUM;
+ if (addSHA512 == false) Hashes &= ~SHA512SUM;
+ return Hashes;
+ }
+
+ public:
+ APT_DEPRECATED bool AddFD(int const Fd, unsigned long long Size, bool const addMD5,
+ bool const addSHA1, bool const addSHA256, bool const addSHA512) {
+ return AddFD(Fd, Size, boolsToFlag(addMD5, addSHA1, addSHA256, addSHA512));
+ };
+
+ APT_DEPRECATED bool AddFD(FileFd &Fd, unsigned long long Size, bool const addMD5,
+ bool const addSHA1, bool const addSHA256, bool const addSHA512) {
+ return AddFD(Fd, Size, boolsToFlag(addMD5, addSHA1, addSHA256, addSHA512));
};
- inline bool Add(const char *Data) {return Add((unsigned char const *)Data,strlen(Data));};
- inline bool AddFD(int const Fd,unsigned long long Size = 0)
- { return AddFD(Fd, Size, true, true, true, true); };
- bool AddFD(int const Fd, unsigned long long Size, bool const addMD5,
- bool const addSHA1, bool const addSHA256, bool const addSHA512);
- inline bool AddFD(FileFd &Fd,unsigned long long Size = 0)
- { return AddFD(Fd, Size, true, true, true, true); };
- bool AddFD(FileFd &Fd, unsigned long long Size, bool const addMD5,
- bool const addSHA1, bool const addSHA256, bool const addSHA512);
- inline bool Add(const unsigned char *Beg,const unsigned char *End)
- {return Add(Beg,End-Beg);};
};
#endif
diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc
index d5e3ccb65..40d332196 100644
--- a/apt-pkg/deb/deblistparser.cc
+++ b/apt-pkg/deb/deblistparser.cc
@@ -194,35 +194,31 @@ bool debListParser::NewVersion(pkgCache::VerIterator &Ver)
/* 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()
+string debListParser::Description(std::string const &lang)
{
- string const lang = DescriptionLanguage();
if (lang.empty())
return Section.FindS("Description");
else
return Section.FindS(string("Description-").append(lang).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()
+ /*}}}*/
+// ListParser::AvailableDescriptionLanguages /*{{{*/
+std::vector<std::string> debListParser::AvailableDescriptionLanguages()
{
- if (Section.FindS("Description").empty() == false)
- return "";
-
- std::vector<string> const lang = APT::Configuration::getLanguages(true);
- for (std::vector<string>::const_iterator l = lang.begin();
- l != lang.end(); ++l)
- if (Section.FindS(string("Description-").append(*l).c_str()).empty() == false)
- return *l;
-
- return "";
+ std::vector<std::string> const understood = APT::Configuration::getLanguages();
+ std::vector<std::string> avail;
+ if (Section.Exists("Description") == true)
+ avail.push_back("");
+ for (std::vector<std::string>::const_iterator lang = understood.begin(); lang != understood.end(); ++lang)
+ {
+ std::string const tagname = "Description-" + *lang;
+ if (Section.Exists(tagname.c_str()) == true)
+ avail.push_back(*lang);
+ }
+ return avail;
}
- /*}}}*/
-// ListParser::Description - Return the description_md5 MD5SumValue /*{{{*/
+ /*}}}*/
+// ListParser::Description_md5 - 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
@@ -233,7 +229,7 @@ MD5SumValue debListParser::Description_md5()
string const value = Section.FindS("Description-md5");
if (value.empty() == true)
{
- std::string const desc = Description() + "\n";
+ std::string const desc = Description("") + "\n";
if (desc == "\n")
return MD5SumValue();
diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h
index 92ec048b1..5a2282f9c 100644
--- a/apt-pkg/deb/deblistparser.h
+++ b/apt-pkg/deb/deblistparser.h
@@ -68,8 +68,8 @@ class debListParser : public pkgCacheGenerator::ListParser
virtual bool ArchitectureAll();
virtual std::string Version();
virtual bool NewVersion(pkgCache::VerIterator &Ver);
- virtual std::string Description();
- virtual std::string DescriptionLanguage();
+ virtual std::string Description(std::string const &lang);
+ virtual std::vector<std::string> AvailableDescriptionLanguages();
virtual MD5SumValue Description_md5();
virtual unsigned short VersionHash();
#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc
index b4839ada4..607dae882 100644
--- a/apt-pkg/deb/debmetaindex.cc
+++ b/apt-pkg/deb/debmetaindex.cc
@@ -258,7 +258,7 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &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, HashString());
+ (*Target)->ShortDesc, HashStringList());
}
delete targets;
diff --git a/apt-pkg/deb/debrecords.cc b/apt-pkg/deb/debrecords.cc
index 6063db5a8..d2c04d8b2 100644
--- a/apt-pkg/deb/debrecords.cc
+++ b/apt-pkg/deb/debrecords.cc
@@ -73,36 +73,17 @@ string debRecordParser::Homepage()
return Section.FindS("Homepage");
}
/*}}}*/
-// RecordParser::MD5Hash - Return the archive hash /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-string debRecordParser::MD5Hash()
-{
- return Section.FindS("MD5Sum");
-}
- /*}}}*/
-// RecordParser::SHA1Hash - Return the archive hash /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-string debRecordParser::SHA1Hash()
-{
- return Section.FindS("SHA1");
-}
- /*}}}*/
-// RecordParser::SHA256Hash - Return the archive hash /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-string debRecordParser::SHA256Hash()
-{
- return Section.FindS("SHA256");
-}
- /*}}}*/
-// RecordParser::SHA512Hash - Return the archive hash /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-string debRecordParser::SHA512Hash()
+// RecordParser::Hashes - return the available archive hashes /*{{{*/
+HashStringList debRecordParser::Hashes() const
{
- return Section.FindS("SHA512");
+ HashStringList hashes;
+ for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type)
+ {
+ std::string const hash = Section.FindS(*type);
+ if (hash.empty() == false)
+ hashes.push_back(HashString(*type, hash));
+ }
+ return hashes;
}
/*}}}*/
// RecordParser::Maintainer - Return the maintainer email /*{{{*/
@@ -125,10 +106,12 @@ string debRecordParser::RecordField(const char *fieldName)
// RecordParser::ShortDesc - Return a 1 line description /*{{{*/
// ---------------------------------------------------------------------
/* */
-string debRecordParser::ShortDesc()
+string debRecordParser::ShortDesc(std::string const &lang)
{
- string Res = LongDesc();
- string::size_type Pos = Res.find('\n');
+ string const Res = LongDesc(lang);
+ if (Res.empty() == true)
+ return "";
+ string::size_type const Pos = Res.find('\n');
if (Pos == string::npos)
return Res;
return string(Res,0,Pos);
@@ -137,26 +120,44 @@ string debRecordParser::ShortDesc()
// RecordParser::LongDesc - Return a longer description /*{{{*/
// ---------------------------------------------------------------------
/* */
-string debRecordParser::LongDesc()
-{
- string orig, dest;
+string debRecordParser::LongDesc(std::string const &lang)
+{
+ string orig;
+ if (lang.empty() == true)
+ {
+ std::vector<string> const lang = APT::Configuration::getLanguages();
+ for (std::vector<string>::const_iterator l = lang.begin();
+ l != lang.end(); ++l)
+ {
+ std::string const tagname = "Description-" + *l;
+ orig = Section.FindS(tagname.c_str());
+ if (orig.empty() == false)
+ break;
+ else if (*l == "en")
+ {
+ orig = Section.FindS("Description");
+ if (orig.empty() == false)
+ break;
+ }
+ }
+ if (orig.empty() == true)
+ orig = Section.FindS("Description");
+ }
+ else
+ {
+ std::string const tagname = "Description-" + lang;
+ orig = Section.FindS(tagname.c_str());
+ if (orig.empty() == true && lang == "en")
+ orig = Section.FindS("Description");
+ }
- if (!Section.FindS("Description").empty())
- orig = Section.FindS("Description").c_str();
- else
- {
- std::vector<string> const lang = APT::Configuration::getLanguages();
- for (std::vector<string>::const_iterator l = lang.begin();
- orig.empty() && l != lang.end(); ++l)
- orig = Section.FindS(string("Description-").append(*l).c_str());
- }
+ char const * const codeset = nl_langinfo(CODESET);
+ if (strcmp(codeset,"UTF-8") != 0) {
+ string dest;
+ UTF8ToCodeset(codeset, orig, &dest);
+ return dest;
+ }
- char const * const codeset = nl_langinfo(CODESET);
- if (strcmp(codeset,"UTF-8") != 0) {
- UTF8ToCodeset(codeset, orig, &dest);
- orig = dest;
- }
-
return orig;
}
/*}}}*/
diff --git a/apt-pkg/deb/debrecords.h b/apt-pkg/deb/debrecords.h
index d572bc5c2..2bd3f3c8f 100644
--- a/apt-pkg/deb/debrecords.h
+++ b/apt-pkg/deb/debrecords.h
@@ -42,17 +42,15 @@ class debRecordParser : public pkgRecords::Parser
// These refer to the archive file for the Version
virtual std::string FileName();
- virtual std::string MD5Hash();
- virtual std::string SHA1Hash();
- virtual std::string SHA256Hash();
- virtual std::string SHA512Hash();
virtual std::string SourcePkg();
virtual std::string SourceVer();
-
+
+ virtual HashStringList Hashes() const;
+
// These are some general stats about the package
virtual std::string Maintainer();
- virtual std::string ShortDesc();
- virtual std::string LongDesc();
+ virtual std::string ShortDesc(std::string const &lang);
+ virtual std::string LongDesc(std::string const &lang);
virtual std::string Name();
virtual std::string Homepage();
diff --git a/apt-pkg/deb/debsrcrecords.cc b/apt-pkg/deb/debsrcrecords.cc
index 7b9a828d3..bf5e56ec9 100644
--- a/apt-pkg/deb/debsrcrecords.cc
+++ b/apt-pkg/deb/debsrcrecords.cc
@@ -124,85 +124,113 @@ bool debSrcRecordParser::Files(std::vector<pkgSrcRecords::File> &List)
{
List.erase(List.begin(),List.end());
- // map from the Hashsum field to the hashsum function,
- // unfortunately this is not a 1:1 mapping from
- // Hashes::SupporedHashes as e.g. Files is a historic name for the md5
- const std::pair<const char*, const char*> SourceHashFields[] = {
- std::make_pair( "Checksums-Sha512", "SHA512"),
- std::make_pair( "Checksums-Sha256", "SHA256"),
- std::make_pair( "Checksums-Sha1", "SHA1"),
- std::make_pair( "Files", "MD5Sum"), // historic Name
- };
-
- for (unsigned int i=0;
- i < sizeof(SourceHashFields)/sizeof(SourceHashFields[0]);
- i++)
- {
- string Files = Sect.FindS(SourceHashFields[i].first);
- if (Files.empty() == true)
- continue;
+ // Stash the / terminated directory prefix
+ string Base = Sect.FindS("Directory");
+ if (Base.empty() == false && Base[Base.length()-1] != '/')
+ Base += '/';
- // Stash the / terminated directory prefix
- string Base = Sect.FindS("Directory");
- if (Base.empty() == false && Base[Base.length()-1] != '/')
- Base += '/';
+ std::vector<std::string> const compExts = APT::Configuration::getCompressorExtensions();
- std::vector<std::string> const compExts = APT::Configuration::getCompressorExtensions();
+ for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type)
+ {
+ // derive field from checksum type
+ std::string checksumField("Checksums-");
+ if (strcmp(*type, "MD5Sum") == 0)
+ checksumField = "Files"; // historic name for MD5 checksums
+ else
+ checksumField.append(*type);
+
+ string const Files = Sect.FindS(checksumField.c_str());
+ if (Files.empty() == true)
+ continue;
// Iterate over the entire list grabbing each triplet
const char *C = Files.c_str();
while (*C != 0)
- {
- pkgSrcRecords::File F;
- string Size;
-
- // Parse each of the elements
- std::string RawHash;
- if (ParseQuoteWord(C, RawHash) == false ||
- ParseQuoteWord(C, Size) == false ||
- ParseQuoteWord(C, F.Path) == false)
- return _error->Error("Error parsing '%s' record",
- SourceHashFields[i].first);
- // assign full hash string
- F.Hash = HashString(SourceHashFields[i].second, RawHash).toStr();
- // API compat hack
- if(strcmp(SourceHashFields[i].second, "MD5Sum") == 0)
- F.MD5Hash = RawHash;
-
- // Parse the size and append the directory
- F.Size = atoi(Size.c_str());
- F.Path = Base + F.Path;
-
- // Try to guess what sort of file it is we are getting.
- string::size_type Pos = F.Path.length()-1;
- while (1)
- {
- string::size_type Tmp = F.Path.rfind('.',Pos);
- if (Tmp == string::npos)
- break;
- if (F.Type == "tar") {
- // source v3 has extension 'debian.tar.*' instead of 'diff.*'
- if (string(F.Path, Tmp+1, Pos-Tmp) == "debian")
- F.Type = "diff";
- break;
- }
- F.Type = string(F.Path,Tmp+1,Pos-Tmp);
-
- if (std::find(compExts.begin(), compExts.end(), std::string(".").append(F.Type)) != compExts.end() ||
- F.Type == "tar")
- {
- Pos = Tmp-1;
- continue;
- }
-
- break;
- }
-
- List.push_back(F);
+ {
+ string hash, size, path;
+
+ // Parse each of the elements
+ if (ParseQuoteWord(C, hash) == false ||
+ ParseQuoteWord(C, size) == false ||
+ ParseQuoteWord(C, path) == false)
+ return _error->Error("Error parsing file record in %s of source package %s", checksumField.c_str(), Package().c_str());
+
+ HashString const hashString(*type, hash);
+ if (Base.empty() == false)
+ path = Base + path;
+
+ // look if we have a record for this file already
+ std::vector<pkgSrcRecords::File>::iterator file = List.begin();
+ for (; file != List.end(); ++file)
+ if (file->Path == path)
+ break;
+
+ // we have it already, store the new hash and be done
+ if (file != List.end())
+ {
+#if __GNUC__ >= 4
+ // set for compatibility only, so warn users not us
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+ if (checksumField == "Files")
+ file->MD5Hash = hash;
+#if __GNUC__ >= 4
+ #pragma GCC diagnostic pop
+#endif
+ // an error here indicates that we have two different hashes for the same file
+ if (file->Hashes.push_back(hashString) == false)
+ return _error->Error("Error parsing checksum in %s of source package %s", checksumField.c_str(), Package().c_str());
+ continue;
+ }
+
+ // we haven't seen this file yet
+ pkgSrcRecords::File F;
+ F.Path = path;
+ F.Size = strtoull(size.c_str(), NULL, 10);
+ F.Hashes.push_back(hashString);
+
+#if __GNUC__ >= 4
+ // set for compatibility only, so warn users not us
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+ if (checksumField == "Files")
+ F.MD5Hash = hash;
+#if __GNUC__ >= 4
+ #pragma GCC diagnostic pop
+#endif
+
+ // Try to guess what sort of file it is we are getting.
+ string::size_type Pos = F.Path.length()-1;
+ while (1)
+ {
+ string::size_type Tmp = F.Path.rfind('.',Pos);
+ if (Tmp == string::npos)
+ break;
+ if (F.Type == "tar") {
+ // source v3 has extension 'debian.tar.*' instead of 'diff.*'
+ if (string(F.Path, Tmp+1, Pos-Tmp) == "debian")
+ F.Type = "diff";
+ break;
+ }
+ F.Type = string(F.Path,Tmp+1,Pos-Tmp);
+
+ if (std::find(compExts.begin(), compExts.end(), std::string(".").append(F.Type)) != compExts.end() ||
+ F.Type == "tar")
+ {
+ Pos = Tmp-1;
+ continue;
+ }
+
+ break;
+ }
+ List.push_back(F);
}
- break;
}
- return (List.size() > 0);
+
+ return true;
}
/*}}}*/
// SrcRecordParser::~SrcRecordParser - Destructor /*{{{*/
diff --git a/apt-pkg/indexcopy.cc b/apt-pkg/indexcopy.cc
index 854ba1bd7..bb3b5d340 100644
--- a/apt-pkg/indexcopy.cc
+++ b/apt-pkg/indexcopy.cc
@@ -516,7 +516,7 @@ bool SigVerify::Verify(string prefix, string file, indexRecords *MetaIndex)
return false;
}
- if (!Record->Hash.VerifyFile(prefix+file))
+ if (!Record->Hashes.VerifyFile(prefix+file))
{
_error->Warning(_("Hash mismatch for: %s"),file.c_str());
return false;
@@ -524,8 +524,10 @@ bool SigVerify::Verify(string prefix, string file, indexRecords *MetaIndex)
if(Debug == true)
{
- cout << "File: " << prefix+file << endl;
- cout << "Expected Hash " << Record->Hash.toStr() << endl;
+ cout << "File: " << prefix+file << endl
+ << "Expected Hash " << endl;
+ for (HashStringList::const_iterator hs = Record->Hashes.begin(); hs != Record->Hashes.end(); ++hs)
+ std::cout << "\t- " << hs->toStr() << std::endl;
}
return true;
diff --git a/apt-pkg/indexrecords.cc b/apt-pkg/indexrecords.cc
index 68ebdce08..5dcaadd76 100644
--- a/apt-pkg/indexrecords.cc
+++ b/apt-pkg/indexrecords.cc
@@ -105,7 +105,7 @@ bool indexRecords::Load(const string Filename) /*{{{*/
return false;
indexRecords::checkSum *Sum = new indexRecords::checkSum;
Sum->MetaKeyFilename = Name;
- Sum->Hash = HashString(HashString::SupportedHashes()[i],Hash);
+ Sum->Hashes.push_back(HashString(HashString::SupportedHashes()[i],Hash));
Sum->Size = Size;
Entries[Name] = Sum;
}
diff --git a/apt-pkg/indexrecords.h b/apt-pkg/indexrecords.h
index 2260a4ae1..14b03c4d5 100644
--- a/apt-pkg/indexrecords.h
+++ b/apt-pkg/indexrecords.h
@@ -55,11 +55,21 @@ class indexRecords
virtual ~indexRecords(){};
};
+#if __GNUC__ >= 4
+ // ensure that con- & de-structor don't trigger this warning
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
struct indexRecords::checkSum
{
std::string MetaKeyFilename;
- HashString Hash;
+ HashStringList Hashes;
unsigned long long Size;
+
+ APT_DEPRECATED HashString Hash;
};
+#if __GNUC__ >= 4
+ #pragma GCC diagnostic pop
+#endif
#endif
diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc
index 5088712a2..2b6153634 100644
--- a/apt-pkg/pkgcache.cc
+++ b/apt-pkg/pkgcache.cc
@@ -168,15 +168,23 @@ bool pkgCache::ReMap(bool const &Errorchecks)
if (Map.Size() < HeaderP->CacheFileSize)
return _error->Error(_("The package cache file is corrupted, it is too small"));
+ if (HeaderP->VerSysName == 0 || HeaderP->Architecture == 0 || HeaderP->Architectures == 0)
+ return _error->Error(_("The package cache file is corrupted"));
+
// Locate our VS..
- if (HeaderP->VerSysName == 0 ||
- (VS = pkgVersioningSystem::GetVS(StrP + HeaderP->VerSysName)) == 0)
+ if ((VS = pkgVersioningSystem::GetVS(StrP + HeaderP->VerSysName)) == 0)
return _error->Error(_("This APT does not support the versioning system '%s'"),StrP + HeaderP->VerSysName);
- // Chcek the arhcitecture
- if (HeaderP->Architecture == 0 ||
- _config->Find("APT::Architecture") != StrP + HeaderP->Architecture)
- return _error->Error(_("The package cache was built for a different architecture"));
+ // Check the architecture
+ std::vector<std::string> archs = APT::Configuration::getArchitectures();
+ std::vector<std::string>::const_iterator a = archs.begin();
+ std::string list = *a;
+ for (++a; a != archs.end(); ++a)
+ list.append(",").append(*a);
+ if (_config->Find("APT::Architecture") != StrP + HeaderP->Architecture ||
+ list != StrP + HeaderP->Architectures)
+ return _error->Error(_("The package cache was built for different architectures: %s vs %s"), StrP + HeaderP->Architectures, list.c_str());
+
return true;
}
/*}}}*/
@@ -822,7 +830,7 @@ int pkgCache::VerIterator::CompareVer(const VerIterator &B) const
// VerIterator::Downloadable - Checks if the version is downloadable /*{{{*/
// ---------------------------------------------------------------------
/* */
-bool pkgCache::VerIterator::Downloadable() const
+APT_PURE bool pkgCache::VerIterator::Downloadable() const
{
VerFileIterator Files = FileList();
for (; Files.end() == false; ++Files)
@@ -835,7 +843,7 @@ bool pkgCache::VerIterator::Downloadable() const
// ---------------------------------------------------------------------
/* This checks to see if any of the versions files are not NotAutomatic.
True if this version is selectable for automatic installation. */
-bool pkgCache::VerIterator::Automatic() const
+APT_PURE bool pkgCache::VerIterator::Automatic() const
{
VerFileIterator Files = FileList();
for (; Files.end() == false; ++Files)
diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h
index 151de7d25..22dc6218c 100644
--- a/apt-pkg/pkgcache.h
+++ b/apt-pkg/pkgcache.h
@@ -286,8 +286,10 @@ struct pkgCache::Header
map_ptrloc StringList;
/** \brief String representing the version system used */
map_ptrloc VerSysName;
- /** \brief Architecture(s) the cache was built against */
+ /** \brief native architecture the cache was built against */
map_ptrloc Architecture;
+ /** \brief all architectures the cache was built against */
+ map_ptrloc Architectures;
/** \brief The maximum size of a raw entry from the original Package file */
unsigned long MaxVerFileSize;
/** \brief The maximum size of a raw entry from the original Translation file */
diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc
index 810f0b022..ac1cea0eb 100644
--- a/apt-pkg/pkgcachegen.cc
+++ b/apt-pkg/pkgcachegen.cc
@@ -74,13 +74,31 @@ pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) :
// Starting header
*Cache.HeaderP = pkgCache::Header();
map_ptrloc const idxVerSysName = WriteStringInMap(_system->VS->Label);
+ if (unlikely(idxVerSysName == 0))
+ return;
Cache.HeaderP->VerSysName = idxVerSysName;
// this pointer is set in ReMap, but we need it now for WriteUniqString
Cache.StringItemP = (pkgCache::StringItem *)Map.Data();
map_ptrloc const idxArchitecture = WriteUniqString(_config->Find("APT::Architecture"));
- Cache.HeaderP->Architecture = idxArchitecture;
- if (unlikely(idxVerSysName == 0 || idxArchitecture == 0))
+ if (unlikely(idxArchitecture == 0))
return;
+ Cache.HeaderP->Architecture = idxArchitecture;
+
+ std::vector<std::string> archs = APT::Configuration::getArchitectures();
+ if (archs.size() > 1)
+ {
+ std::vector<std::string>::const_iterator a = archs.begin();
+ std::string list = *a;
+ for (++a; a != archs.end(); ++a)
+ list.append(",").append(*a);
+ map_ptrloc const idxArchitectures = WriteStringInMap(list);
+ if (unlikely(idxArchitectures == 0))
+ return;
+ Cache.HeaderP->Architectures = idxArchitectures;
+ }
+ else
+ Cache.HeaderP->Architectures = idxArchitecture;
+
Cache.ReMap();
}
else
@@ -302,10 +320,9 @@ bool pkgCacheGenerator::MergeListPackage(ListParser &List, pkgCache::PkgIterator
// Find the right version to write the description
MD5SumValue CurMd5 = List.Description_md5();
- if (CurMd5.Value().empty() == true || List.Description().empty() == true)
+ if (CurMd5.Value().empty() == true && List.Description("").empty() == true)
return true;
- std::string CurLang = List.DescriptionLanguage();
-
+ std::vector<std::string> availDesc = List.AvailableDescriptionLanguages();
for (Ver = Pkg.VersionList(); Ver.end() == false; ++Ver)
{
pkgCache::DescIterator VerDesc = Ver.DescriptionList();
@@ -314,31 +331,16 @@ bool pkgCacheGenerator::MergeListPackage(ListParser &List, pkgCache::PkgIterator
if (VerDesc.end() == true || MD5SumValue(VerDesc.md5()) != CurMd5)
continue;
- // don't add a new description if we have one for the given
- // md5 && language
- if (IsDuplicateDescription(VerDesc, CurMd5, CurLang) == true)
- continue;
-
- pkgCache::DescIterator Desc;
- Dynamic<pkgCache::DescIterator> DynDesc(Desc);
-
- map_ptrloc const descindex = NewDescription(Desc, CurLang, CurMd5, VerDesc->md5sum);
- if (unlikely(descindex == 0 && _error->PendingError()))
- return _error->Error(_("Error occurred while processing %s (%s%d)"),
- Pkg.Name(), "NewDescription", 1);
-
- Desc->ParentPkg = Pkg.Index();
-
- // we add at the end, so that the start is constant as we need
- // that to be able to efficiently share these lists
- VerDesc = Ver.DescriptionList(); // old value might be invalid after ReMap
- for (;VerDesc.end() == false && VerDesc->NextDesc != 0; ++VerDesc);
- map_ptrloc * const LastNextDesc = (VerDesc.end() == true) ? &Ver->DescriptionList : &VerDesc->NextDesc;
- *LastNextDesc = descindex;
+ map_ptrloc md5idx = VerDesc->md5sum;
+ for (std::vector<std::string>::const_iterator CurLang = availDesc.begin(); CurLang != availDesc.end(); ++CurLang)
+ {
+ // don't add a new description if we have one for the given
+ // md5 && language
+ if (IsDuplicateDescription(VerDesc, CurMd5, *CurLang) == true)
+ continue;
- if (NewFileDesc(Desc,List) == false)
- return _error->Error(_("Error occurred while processing %s (%s%d)"),
- Pkg.Name(), "NewFileDesc", 1);
+ AddNewDescription(List, Ver, *CurLang, CurMd5, md5idx);
+ }
// we can stop here as all "same" versions will share the description
break;
@@ -486,11 +488,10 @@ bool pkgCacheGenerator::MergeListVersion(ListParser &List, pkgCache::PkgIterator
return true;
}
- /* Record the Description (it is not translated) */
+ /* Record the Description(s) based on their master md5sum */
MD5SumValue CurMd5 = List.Description_md5();
- if (CurMd5.Value().empty() == true || List.Description().empty() == true)
+ if (CurMd5.Value().empty() == true && List.Description("").empty() == true)
return true;
- std::string CurLang = List.DescriptionLanguage();
/* Before we add a new description we first search in the group for
a version with a description of the same MD5 - if so we reuse this
@@ -501,28 +502,44 @@ bool pkgCacheGenerator::MergeListVersion(ListParser &List, pkgCache::PkgIterator
for (pkgCache::VerIterator V = P.VersionList();
V.end() == false; ++V)
{
- if (IsDuplicateDescription(V.DescriptionList(), CurMd5, "") == false)
+ if (V->DescriptionList == 0 || MD5SumValue(V.DescriptionList().md5()) != CurMd5)
continue;
Ver->DescriptionList = V->DescriptionList;
- return true;
}
}
- // We haven't found reusable descriptions, so add the first description
- pkgCache::DescIterator Desc = Ver.DescriptionList();
+ // We haven't found reusable descriptions, so add the first description(s)
+ map_ptrloc md5idx = Ver->DescriptionList == 0 ? 0 : Ver.DescriptionList()->md5sum;
+ std::vector<std::string> availDesc = List.AvailableDescriptionLanguages();
+ for (std::vector<std::string>::const_iterator CurLang = availDesc.begin(); CurLang != availDesc.end(); ++CurLang)
+ if (AddNewDescription(List, Ver, *CurLang, CurMd5, md5idx) == false)
+ return false;
+ return true;
+}
+ /*}}}*/
+bool pkgCacheGenerator::AddNewDescription(ListParser &List, pkgCache::VerIterator &Ver, std::string const &lang, MD5SumValue const &CurMd5, map_ptrloc &md5idx) /*{{{*/
+{
+ pkgCache::DescIterator Desc;
Dynamic<pkgCache::DescIterator> DynDesc(Desc);
- map_ptrloc const descindex = NewDescription(Desc, CurLang, CurMd5, 0);
+ map_ptrloc const descindex = NewDescription(Desc, lang, CurMd5, md5idx);
if (unlikely(descindex == 0 && _error->PendingError()))
return _error->Error(_("Error occurred while processing %s (%s%d)"),
- Pkg.Name(), "NewDescription", 2);
+ Ver.ParentPkg().Name(), "NewDescription", 1);
+
+ md5idx = Desc->md5sum;
+ Desc->ParentPkg = Ver.ParentPkg().Index();
- Desc->ParentPkg = Pkg.Index();
- Ver->DescriptionList = descindex;
+ // we add at the end, so that the start is constant as we need
+ // that to be able to efficiently share these lists
+ pkgCache::DescIterator VerDesc = Ver.DescriptionList(); // old value might be invalid after ReMap
+ for (;VerDesc.end() == false && VerDesc->NextDesc != 0; ++VerDesc);
+ map_ptrloc * const LastNextDesc = (VerDesc.end() == true) ? &Ver->DescriptionList : &VerDesc->NextDesc;
+ *LastNextDesc = descindex;
if (NewFileDesc(Desc,List) == false)
return _error->Error(_("Error occurred while processing %s (%s%d)"),
- Pkg.Name(), "NewFileDesc", 2);
+ Ver.ParentPkg().Name(), "NewFileDesc", 1);
return true;
}
diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h
index 1e1a71026..d275c1e42 100644
--- a/apt-pkg/pkgcachegen.h
+++ b/apt-pkg/pkgcachegen.h
@@ -125,6 +125,9 @@ class pkgCacheGenerator /*{{{*/
APT_HIDDEN bool AddImplicitDepends(pkgCache::GrpIterator &G, pkgCache::PkgIterator &P,
pkgCache::VerIterator &V);
APT_HIDDEN bool AddImplicitDepends(pkgCache::VerIterator &V, pkgCache::PkgIterator &D);
+
+ APT_HIDDEN bool AddNewDescription(ListParser &List, pkgCache::VerIterator &Ver,
+ std::string const &lang, MD5SumValue const &CurMd5, map_ptrloc &md5idx);
};
/*}}}*/
// This is the abstract package list parser class. /*{{{*/
@@ -160,8 +163,8 @@ class pkgCacheGenerator::ListParser
virtual bool ArchitectureAll() = 0;
virtual std::string Version() = 0;
virtual bool NewVersion(pkgCache::VerIterator &Ver) = 0;
- virtual std::string Description() = 0;
- virtual std::string DescriptionLanguage() = 0;
+ virtual std::string Description(std::string const &lang) = 0;
+ virtual std::vector<std::string> AvailableDescriptionLanguages() = 0;
virtual MD5SumValue Description_md5() = 0;
virtual unsigned short VersionHash() = 0;
/** compare currently parsed version with given version
diff --git a/apt-pkg/pkgrecords.h b/apt-pkg/pkgrecords.h
index b5237b3a0..a902da8b8 100644
--- a/apt-pkg/pkgrecords.h
+++ b/apt-pkg/pkgrecords.h
@@ -18,6 +18,8 @@
#define PKGLIB_PKGRECORDS_H
#include <apt-pkg/pkgcache.h>
+#include <apt-pkg/hashes.h>
+#include <apt-pkg/macros.h>
#include <string>
#include <vector>
@@ -56,17 +58,39 @@ class pkgRecords::Parser /*{{{*/
// These refer to the archive file for the Version
virtual std::string FileName() {return std::string();};
- virtual std::string MD5Hash() {return std::string();};
- virtual std::string SHA1Hash() {return std::string();};
- virtual std::string SHA256Hash() {return std::string();};
- virtual std::string SHA512Hash() {return std::string();};
virtual std::string SourcePkg() {return std::string();};
virtual std::string SourceVer() {return std::string();};
+ /** return all known hashes in this record.
+ *
+ * For authentication proposes packages come with hashsums which
+ * this method is supposed to parse and return so that clients can
+ * choose the hash to be used.
+ */
+ virtual HashStringList Hashes() const { return HashStringList(); };
+ APT_DEPRECATED std::string MD5Hash() const { return GetHashFromHashes("MD5Sum"); };
+ APT_DEPRECATED std::string SHA1Hash() const { return GetHashFromHashes("SHA1"); };
+ APT_DEPRECATED std::string SHA256Hash() const { return GetHashFromHashes("SHA256"); };
+ APT_DEPRECATED std::string SHA512Hash() const { return GetHashFromHashes("SHA512"); };
+
// These are some general stats about the package
virtual std::string Maintainer() {return std::string();};
- virtual std::string ShortDesc() {return std::string();};
- virtual std::string LongDesc() {return std::string();};
+ /** return short description in language from record.
+ *
+ * @see #LongDesc
+ */
+ virtual std::string ShortDesc(std::string const &/*lang*/) {return std::string();};
+ /** return long description in language from record.
+ *
+ * If \b lang is empty the "best" available language will be
+ * returned as determined by the APT::Languages configuration.
+ * If a (requested) language can't be found in this record an empty
+ * string will be returned.
+ */
+ virtual std::string LongDesc(std::string const &/*lang*/) {return std::string();};
+ std::string ShortDesc() {return ShortDesc("");};
+ std::string LongDesc() {return LongDesc("");};
+
virtual std::string Name() {return std::string();};
virtual std::string Homepage() {return std::string();}
@@ -77,6 +101,14 @@ class pkgRecords::Parser /*{{{*/
virtual void GetRec(const char *&Start,const char *&Stop) {Start = Stop = 0;};
virtual ~Parser() {};
+
+ private:
+ APT_HIDDEN std::string GetHashFromHashes(char const * const type) const
+ {
+ HashStringList const hashes = Hashes();
+ HashString const * const hs = hashes.find(type);
+ return hs != NULL ? hs->HashValue() : "";
+ };
};
/*}}}*/
#endif
diff --git a/apt-pkg/srcrecords.h b/apt-pkg/srcrecords.h
index 58a5e242f..69b3cfd99 100644
--- a/apt-pkg/srcrecords.h
+++ b/apt-pkg/srcrecords.h
@@ -14,6 +14,7 @@
#define PKGLIB_SRCRECORDS_H
#include <apt-pkg/macros.h>
+#include <apt-pkg/hashes.h>
#include <string>
#include <vector>
@@ -29,16 +30,24 @@ class pkgSrcRecords
{
public:
+#if __GNUC__ >= 4
+ // ensure that con- & de-structor don't trigger this warning
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
// Describes a single file
struct File
{
- std::string MD5Hash;
- std::string Hash;
- unsigned long Size;
std::string Path;
std::string Type;
+ unsigned long long Size;
+ HashStringList Hashes;
+ APT_DEPRECATED std::string MD5Hash;
};
-
+#if __GNUC__ >= 4
+ #pragma GCC diagnostic pop
+#endif
+
// Abstract parser for each source record
class Parser
{
diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc
index 009ed7d74..52f4da2d5 100644
--- a/apt-pkg/tagfile.cc
+++ b/apt-pkg/tagfile.cc
@@ -47,6 +47,22 @@ public:
unsigned long long Size;
};
+static unsigned long AlphaHash(const char *Text, size_t Length) /*{{{*/
+{
+ /* This very simple hash function for the last 8 letters gives
+ very good performance on the debian package files */
+ if (Length > 8)
+ {
+ Text += (Length - 8);
+ Length = 8;
+ }
+ unsigned long Res = 0;
+ for (size_t i = 0; i < Length; ++i)
+ Res = ((unsigned long)(Text[i]) & 0xDF) ^ (Res << 1);
+ return Res & 0xFF;
+}
+ /*}}}*/
+
// TagFile::pkgTagFile - Constructor /*{{{*/
// ---------------------------------------------------------------------
/* */
@@ -139,18 +155,23 @@ bool pkgTagFile::Resize(unsigned long long const newSize)
*/
bool pkgTagFile::Step(pkgTagSection &Tag)
{
- while (Tag.Scan(d->Start,d->End - d->Start) == false)
+ if(Tag.Scan(d->Start,d->End - d->Start) == false)
{
- if (Fill() == false)
- return false;
-
- if(Tag.Scan(d->Start,d->End - d->Start))
- break;
+ do
+ {
+ if (Fill() == false)
+ return false;
+
+ if(Tag.Scan(d->Start,d->End - d->Start, false))
+ break;
+
+ if (Resize() == false)
+ return _error->Error(_("Unable to parse package file %s (1)"),
+ d->Fd.Name().c_str());
- if (Resize() == false)
- return _error->Error(_("Unable to parse package file %s (1)"),
- d->Fd.Name().c_str());
+ } while (Tag.Scan(d->Start,d->End - d->Start, false) == false);
}
+
d->Start += Tag.size();
d->iOffset += Tag.size();
@@ -244,7 +265,7 @@ bool pkgTagFile::Jump(pkgTagSection &Tag,unsigned long long Offset)
if (Fill() == false)
return false;
- if (Tag.Scan(d->Start, d->End - d->Start) == false)
+ if (Tag.Scan(d->Start, d->End - d->Start, false) == false)
return _error->Error(_("Unable to parse package file %s (2)"),d->Fd.Name().c_str());
return true;
@@ -254,27 +275,46 @@ bool pkgTagFile::Jump(pkgTagSection &Tag,unsigned long long Offset)
// ---------------------------------------------------------------------
/* */
pkgTagSection::pkgTagSection()
- : Section(0), TagCount(0), d(NULL), Stop(0)
+ : Section(0), d(NULL), Stop(0)
{
- memset(&Indexes, 0, sizeof(Indexes));
- memset(&AlphaIndexes, 0, sizeof(AlphaIndexes));
+ memset(&LookupTable, 0, sizeof(LookupTable));
}
/*}}}*/
// TagSection::Scan - Scan for the end of the header information /*{{{*/
-// ---------------------------------------------------------------------
-/* This looks for the first double new line in the data stream.
- It also indexes the tags in the section. */
-bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength)
+bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const Restart)
{
+ Section = Start;
const char *End = Start + MaxLength;
- Stop = Section = Start;
- memset(AlphaIndexes,0,sizeof(AlphaIndexes));
+
+ if (Restart == false && Tags.empty() == false)
+ {
+ Stop = Section + Tags.back().StartTag;
+ if (End <= Stop)
+ return false;
+ Stop = (const char *)memchr(Stop,'\n',End - Stop);
+ if (Stop == NULL)
+ return false;
+ ++Stop;
+ }
+ else
+ {
+ Stop = Section;
+ if (Tags.empty() == false)
+ {
+ memset(&LookupTable, 0, sizeof(LookupTable));
+ Tags.clear();
+ }
+ Tags.reserve(0x100);
+ }
+ size_t TagCount = Tags.size();
if (Stop == 0)
return false;
- TagCount = 0;
- while (TagCount+1 < sizeof(Indexes)/sizeof(Indexes[0]) && Stop < End)
+ TagData lastTagData(0);
+ lastTagData.EndTag = 0;
+ unsigned long lastTagHash = 0;
+ while (Stop < End)
{
TrimRecord(true,End);
@@ -286,12 +326,39 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength)
// Start a new index and add it to the hash
if (isspace(Stop[0]) == 0)
{
- Indexes[TagCount++] = Stop - Section;
- AlphaIndexes[AlphaHash(Stop,End)] = TagCount;
+ // store the last found tag
+ if (lastTagData.EndTag != 0)
+ {
+ if (LookupTable[lastTagHash] != 0)
+ lastTagData.NextInBucket = LookupTable[lastTagHash];
+ LookupTable[lastTagHash] = TagCount;
+ Tags.push_back(lastTagData);
+ }
+
+ ++TagCount;
+ lastTagData = TagData(Stop - Section);
+ // find the colon separating tag and value
+ char const * Colon = (char const *) memchr(Stop, ':', End - Stop);
+ if (Colon == NULL)
+ return false;
+ // find the end of the tag (which might or might not be the colon)
+ char const * EndTag = Colon;
+ --EndTag;
+ for (; EndTag > Stop && isspace(*EndTag) != 0; --EndTag)
+ ;
+ ++EndTag;
+ lastTagData.EndTag = EndTag - Section;
+ lastTagHash = AlphaHash(Stop, EndTag - Stop);
+ // find the beginning of the value
+ Stop = Colon + 1;
+ for (; isspace(*Stop) != 0; ++Stop);
+ if (Stop >= End)
+ return false;
+ lastTagData.StartValue = Stop - Section;
}
Stop = (const char *)memchr(Stop,'\n',End - Stop);
-
+
if (Stop == 0)
return false;
@@ -302,7 +369,16 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength)
// Double newline marks the end of the record
if (Stop+1 < End && Stop[1] == '\n')
{
- Indexes[TagCount] = Stop - Section;
+ if (lastTagData.EndTag != 0)
+ {
+ if (LookupTable[lastTagHash] != 0)
+ lastTagData.NextInBucket = LookupTable[lastTagHash];
+ LookupTable[lastTagHash] = TagCount;
+ Tags.push_back(lastTagData);
+ }
+
+ TagData const td(Stop - Section);
+ Tags.push_back(td);
TrimRecord(false,End);
return true;
}
@@ -331,8 +407,8 @@ void pkgTagSection::Trim()
for (; Stop > Section + 2 && (Stop[-2] == '\n' || Stop[-2] == '\r'); Stop--);
}
/*}}}*/
-// TagSection::Exists - return True if a tag exists /*{{{*/
-bool pkgTagSection::Exists(const char* const Tag)
+// TagSection::Exists - return True if a tag exists /*{{{*/
+bool pkgTagSection::Exists(const char* const Tag) const
{
unsigned int tmp;
return Find(Tag, tmp);
@@ -343,73 +419,43 @@ bool pkgTagSection::Exists(const char* const Tag)
/* This searches the section for a tag that matches the given string. */
bool pkgTagSection::Find(const char *Tag,unsigned int &Pos) const
{
- unsigned int Length = strlen(Tag);
- unsigned int I = AlphaIndexes[AlphaHash(Tag)];
- if (I == 0)
+ size_t const Length = strlen(Tag);
+ unsigned int Bucket = LookupTable[AlphaHash(Tag, Length)];
+ if (Bucket == 0)
return false;
- I--;
-
- for (unsigned int Counter = 0; Counter != TagCount; Counter++,
- I = (I+1)%TagCount)
+
+ for (; Bucket != 0; Bucket = Tags[Bucket - 1].NextInBucket)
{
- const char *St;
- St = Section + Indexes[I];
- if (strncasecmp(Tag,St,Length) != 0)
+ if ((Tags[Bucket - 1].EndTag - Tags[Bucket - 1].StartTag) != Length)
continue;
- // Make sure the colon is in the right place
- const char *C = St + Length;
- for (; isspace(*C) != 0; C++);
- if (*C != ':')
+ char const * const St = Section + Tags[Bucket - 1].StartTag;
+ if (strncasecmp(Tag,St,Length) != 0)
continue;
- Pos = I;
+
+ Pos = Bucket - 1;
return true;
}
Pos = 0;
return false;
}
- /*}}}*/
-// TagSection::Find - Locate a tag /*{{{*/
-// ---------------------------------------------------------------------
-/* This searches the section for a tag that matches the given string. */
bool pkgTagSection::Find(const char *Tag,const char *&Start,
const char *&End) const
{
- unsigned int Length = strlen(Tag);
- unsigned int I = AlphaIndexes[AlphaHash(Tag)];
- if (I == 0)
+ unsigned int Pos;
+ if (Find(Tag, Pos) == false)
return false;
- I--;
-
- for (unsigned int Counter = 0; Counter != TagCount; Counter++,
- I = (I+1)%TagCount)
- {
- const char *St;
- St = Section + Indexes[I];
- if (strncasecmp(Tag,St,Length) != 0)
- continue;
-
- // Make sure the colon is in the right place
- const char *C = St + Length;
- for (; isspace(*C) != 0; C++);
- if (*C != ':')
- continue;
- // Strip off the gunk from the start end
- Start = C;
- End = Section + Indexes[I+1];
- if (Start >= End)
- return _error->Error("Internal parsing error");
-
- for (; (isspace(*Start) != 0 || *Start == ':') && Start < End; Start++);
- for (; isspace(End[-1]) != 0 && End > Start; End--);
-
- return true;
- }
-
- Start = End = 0;
- return false;
+ Start = Section + Tags[Pos].StartValue;
+ // Strip off the gunk from the end
+ End = Section + Tags[Pos + 1].StartTag;
+ if (unlikely(Start > End))
+ return _error->Error("Internal parsing error");
+
+ for (; isspace(End[-1]) != 0 && End > Start; --End);
+
+ return true;
}
/*}}}*/
// TagSection::FindS - Find a string /*{{{*/
@@ -504,6 +550,13 @@ bool pkgTagSection::FindFlag(unsigned long &Flags, unsigned long Flag,
return true;
}
/*}}}*/
+APT_PURE unsigned int pkgTagSection::Count() const { /*{{{*/
+ if (Tags.empty() == true)
+ return 0;
+ // the last element is just marking the end and isn't a real one
+ return Tags.size() - 1;
+}
+ /*}}}*/
// TFRewrite - Rewrite a control record /*{{{*/
// ---------------------------------------------------------------------
/* This writes the control record to stdout rewriting it as necessary. The
diff --git a/apt-pkg/tagfile.h b/apt-pkg/tagfile.h
index d1a24ba45..b0cfab759 100644
--- a/apt-pkg/tagfile.h
+++ b/apt-pkg/tagfile.h
@@ -25,6 +25,8 @@
#include <stdio.h>
#include <string>
+#include <vector>
+#include <list>
#ifndef APT_8_CLEANER_HEADERS
#include <apt-pkg/fileutl.h>
@@ -35,23 +37,20 @@ class FileFd;
class pkgTagSection
{
const char *Section;
- // We have a limit of 256 tags per section.
- unsigned int Indexes[256];
- unsigned int AlphaIndexes[0x100];
- unsigned int TagCount;
+ struct TagData {
+ unsigned int StartTag;
+ unsigned int EndTag;
+ unsigned int StartValue;
+ unsigned int NextInBucket;
+
+ TagData(unsigned int const StartTag) : StartTag(StartTag), NextInBucket(0) {}
+ };
+ std::vector<TagData> Tags;
+ unsigned int LookupTable[0x100];
+
// dpointer placeholder (for later in case we need it)
void *d;
- /* This very simple hash function for the 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) & 0xDF) ^ (Res << 1);
- return Res & 0xFF;
- }
-
protected:
const char *Stop;
@@ -69,17 +68,39 @@ class pkgTagSection
unsigned long Flag) const;
bool static FindFlag(unsigned long &Flags, unsigned long Flag,
const char* Start, const char* Stop);
- bool Scan(const char *Start,unsigned long MaxLength);
+
+ /** \brief searches the boundaries of the current section
+ *
+ * While parameter Start marks the beginning of the section, this method
+ * will search for the first double newline in the data stream which marks
+ * the end of the section. It also does a first pass over the content of
+ * the section parsing it as encountered for processing later on by Find
+ *
+ * @param Start is the beginning of the section
+ * @param MaxLength is the size of valid data in the stream pointed to by Start
+ * @param Restart if enabled internal state will be cleared, otherwise it is
+ * assumed that now more data is available in the stream and the parsing will
+ * start were it encountered insufficent data the last time.
+ *
+ * @return \b true if section end was found, \b false otherwise.
+ * Beware that internal state will be inconsistent if \b false is returned!
+ */
+ APT_MUSTCHECK bool Scan(const char *Start, unsigned long MaxLength, bool const Restart = true);
inline unsigned long size() const {return Stop - Section;};
void Trim();
virtual void TrimRecord(bool BeforeRecord, const char* &End);
-
- inline unsigned int Count() const {return TagCount;};
- bool Exists(const char* const Tag);
-
+
+ /** \brief amount of Tags in the current section
+ *
+ * Note: if a Tag is mentioned repeatly it will be counted multiple
+ * times, but only the last occurance is available via Find methods.
+ */
+ unsigned int Count() const;
+ bool Exists(const char* const Tag) const;
+
inline void Get(const char *&Start,const char *&Stop,unsigned int I) const
- {Start = Section + Indexes[I]; Stop = Section + Indexes[I+1];}
-
+ {Start = Section + Tags[I].StartTag; Stop = Section + Tags[I+1].StartTag;}
+
inline void GetSection(const char *&Start,const char *&Stop) const
{
Start = Section;
diff --git a/apt-private/acqprogress.cc b/apt-private/acqprogress.cc
index 4bcfd8f00..17a12799c 100644
--- a/apt-private/acqprogress.cc
+++ b/apt-private/acqprogress.cc
@@ -140,6 +140,9 @@ void AcqTextStatus::Stop()
if (Quiet <= 0)
cout << '\r' << BlankLine << '\r' << flush;
+ if (_config->FindB("quiet::NoStatistic", false) == true)
+ return;
+
if (FetchedBytes != 0 && _error->PendingError() == false)
ioprintf(cout,_("Fetched %sB in %s (%sB/s)\n"),
SizeToStr(FetchedBytes).c_str(),
diff --git a/cmdline/apt-extracttemplates.cc b/cmdline/apt-extracttemplates.cc
index e4428e051..7be59b9f8 100644
--- a/cmdline/apt-extracttemplates.cc
+++ b/cmdline/apt-extracttemplates.cc
@@ -103,10 +103,12 @@ bool DebFile::DoItem(Item &I, int &Fd)
if (strcmp(I.Name, "control") == 0)
{
delete [] Control;
- Control = new char[I.Size+1];
- Control[I.Size] = 0;
+ Control = new char[I.Size+3];
+ Control[I.Size] = '\n';
+ Control[I.Size + 1] = '\n';
+ Control[I.Size + 2] = '\0';
Which = IsControl;
- ControlLen = I.Size;
+ ControlLen = I.Size + 3;
// make it call the Process method below. this is so evil
Fd = -2;
}
@@ -162,9 +164,10 @@ bool DebFile::Process(Item &/*I*/, const unsigned char *data,
bool DebFile::ParseInfo()
{
if (Control == NULL) return false;
-
+
pkgTagSection Section;
- Section.Scan(Control, ControlLen);
+ if (Section.Scan(Control, ControlLen) == false)
+ return false;
Package = Section.FindS("Package");
Version = GetInstalledVer(Package);
diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc
index 1148dbbf3..3388351d9 100644
--- a/cmdline/apt-get.cc
+++ b/cmdline/apt-get.cc
@@ -828,20 +828,25 @@ static bool DoSource(CommandLine &CmdL)
queued.insert(Last->Index().ArchiveURI(I->Path));
// check if we have a file with that md5 sum already localy
- if(!I->Hash.empty() && FileExists(flNotDir(I->Path)))
- {
- HashString hash_string = HashString(I->Hash);
- if(hash_string.VerifyFile(flNotDir(I->Path)))
+ std::string localFile = flNotDir(I->Path);
+ if (FileExists(localFile) == true)
+ if(I->Hashes.VerifyFile(localFile) == true)
{
ioprintf(c1out,_("Skipping already downloaded file '%s'\n"),
- flNotDir(I->Path).c_str());
+ localFile.c_str());
continue;
}
+
+ // see if we have a hash (Acquire::ForceHash is the only way to have none)
+ if (I->Hashes.usable() == false && _config->FindB("APT::Get::AllowUnauthenticated",false) == false)
+ {
+ ioprintf(c1out, "Skipping download of file '%s' as requested hashsum is not available for authentication\n",
+ localFile.c_str());
+ continue;
}
new pkgAcqFile(&Fetcher,Last->Index().ArchiveURI(I->Path),
- I->Hash,I->Size,
- Last->Index().SourceInfo(*Last,*I),Src);
+ I->Hashes, I->Size, Last->Index().SourceInfo(*Last,*I), Src);
}
}
diff --git a/doc/apt.conf.5.xml b/doc/apt.conf.5.xml
index fcbf20dac..21878e262 100644
--- a/doc/apt.conf.5.xml
+++ b/doc/apt.conf.5.xml
@@ -390,9 +390,9 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";};
<para>The setting <literal>Acquire::http::Pipeline-Depth</literal> can be used to
enable HTTP pipelining (RFC 2616 section 8.1.2.2) which can be beneficial e.g. on
high-latency connections. It specifies how many requests are sent in a pipeline.
- Previous APT versions had a default of 10 for this setting, but the default value
- is now 0 (= disabled) to avoid problems with the ever-growing amount of webservers
- and proxies which choose to not conform to the HTTP/1.1 specification.</para>
+ APT tries to detect and workaround misbehaving webservers and proxies at runtime, but
+ if you know that yours does not conform to the HTTP/1.1 specification pipelining can
+ be disabled by setting the value to 0. It is enabled by default with the value 10.</para>
<para><literal>Acquire::http::AllowRedirect</literal> controls whether APT will follow
redirects, which is enabled by default.</para>
diff --git a/ftparchive/cachedb.cc b/ftparchive/cachedb.cc
index e56deae1e..be54ea62c 100644
--- a/ftparchive/cachedb.cc
+++ b/ftparchive/cachedb.cc
@@ -21,11 +21,13 @@
#include <apt-pkg/fileutl.h>
#include <apt-pkg/debfile.h>
#include <apt-pkg/gpgv.h>
+#include <apt-pkg/hashes.h>
#include <netinet/in.h> // htonl, etc
#include <ctype.h>
#include <stddef.h>
#include <sys/stat.h>
+#include <strings.h>
#include "cachedb.h"
@@ -206,15 +208,10 @@ bool CacheDB::GetCurStat()
/*}}}*/
// CacheDB::GetFileInfo - Get all the info about the file /*{{{*/
// ---------------------------------------------------------------------
-bool CacheDB::GetFileInfo(std::string const &FileName, bool const &DoControl,
- bool const &DoContents,
- bool const &GenContentsOnly,
- bool const &DoSource,
- bool const &DoMD5, bool const &DoSHA1,
- bool const &DoSHA256, bool const &DoSHA512,
+bool CacheDB::GetFileInfo(std::string const &FileName, bool const &DoControl, bool const &DoContents,
+ bool const &GenContentsOnly, bool const DoSource, unsigned int const DoHashes,
bool const &checkMtime)
{
- bool result = true;
this->FileName = FileName;
if (GetCurStat() == false)
@@ -222,31 +219,28 @@ bool CacheDB::GetFileInfo(std::string const &FileName, bool const &DoControl,
OldStat = CurStat;
if (GetFileStat(checkMtime) == false)
- return false;
+ return false;
/* if mtime changed, update CurStat from disk */
if (checkMtime == true && OldStat.mtime != CurStat.mtime)
CurStat.Flags = FlSize;
Stats.Bytes += CurStat.FileSize;
- Stats.Packages++;
+ ++Stats.Packages;
if ((DoControl && LoadControl() == false)
- || (DoContents && LoadContents(GenContentsOnly) == false)
- || (DoSource && LoadSource() == false)
- || (DoMD5 && GetMD5(false) == false)
- || (DoSHA1 && GetSHA1(false) == false)
- || (DoSHA256 && GetSHA256(false) == false)
- || (DoSHA512 && GetSHA512(false) == false) )
+ || (DoContents && LoadContents(GenContentsOnly) == false)
+ || (DoSource && LoadSource() == false)
+ || (DoHashes != 0 && GetHashes(false, DoHashes) == false)
+ )
{
- result = false;
+ return false;
}
-
- return result;
+
+ return true;
}
/*}}}*/
-
-bool CacheDB::LoadSource()
+bool CacheDB::LoadSource() /*{{{*/
{
// Try to read the control information out of the DB.
if ((CurStat.Flags & FlSource) == FlSource)
@@ -276,7 +270,7 @@ bool CacheDB::LoadSource()
return true;
}
-
+ /*}}}*/
// CacheDB::LoadControl - Load Control information /*{{{*/
// ---------------------------------------------------------------------
/* */
@@ -345,7 +339,7 @@ bool CacheDB::LoadContents(bool const &GenOnly)
return true;
}
/*}}}*/
-
+// CacheDB::GetHashes - Get the hashs /*{{{*/
static std::string bytes2hex(uint8_t *bytes, size_t length) {
char buf[3];
std::string space;
@@ -375,125 +369,59 @@ static void hex2bytes(uint8_t *bytes, const char *hex, int length) {
bytes++;
}
}
-
-// CacheDB::GetMD5 - Get the MD5 hash /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool CacheDB::GetMD5(bool const &GenOnly)
+bool CacheDB::GetHashes(bool const GenOnly, unsigned int const DoHashes)
{
- // Try to read the control information out of the DB.
- if ((CurStat.Flags & FlMD5) == FlMD5)
- {
- if (GenOnly == true)
- return true;
-
- MD5Res = bytes2hex(CurStat.MD5, sizeof(CurStat.MD5));
- return true;
- }
-
- Stats.MD5Bytes += CurStat.FileSize;
-
- if (OpenFile() == false)
- return false;
+ unsigned int FlHashes = DoHashes & (Hashes::MD5SUM | Hashes::SHA1SUM | Hashes::SHA256SUM | Hashes::SHA512SUM);
+ HashesList.clear();
- MD5Summation MD5;
- if (Fd->Seek(0) == false || MD5.AddFD(*Fd, CurStat.FileSize) == false)
- return false;
-
- MD5Res = MD5.Result();
- hex2bytes(CurStat.MD5, MD5Res.data(), sizeof(CurStat.MD5));
- CurStat.Flags |= FlMD5;
- return true;
-}
- /*}}}*/
-// CacheDB::GetSHA1 - Get the SHA1 hash /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool CacheDB::GetSHA1(bool const &GenOnly)
-{
- // Try to read the control information out of the DB.
- if ((CurStat.Flags & FlSHA1) == FlSHA1)
+ if (FlHashes != 0)
{
- if (GenOnly == true)
- return true;
+ if (OpenFile() == false)
+ return false;
- SHA1Res = bytes2hex(CurStat.SHA1, sizeof(CurStat.SHA1));
- return true;
- }
-
- Stats.SHA1Bytes += CurStat.FileSize;
-
- if (OpenFile() == false)
- return false;
+ Hashes hashes;
+ if (Fd->Seek(0) == false || hashes.AddFD(*Fd, CurStat.FileSize, FlHashes) == false)
+ return false;
- SHA1Summation SHA1;
- if (Fd->Seek(0) == false || SHA1.AddFD(*Fd, CurStat.FileSize) == false)
- return false;
-
- SHA1Res = SHA1.Result();
- hex2bytes(CurStat.SHA1, SHA1Res.data(), sizeof(CurStat.SHA1));
- CurStat.Flags |= FlSHA1;
- return true;
-}
- /*}}}*/
-// CacheDB::GetSHA256 - Get the SHA256 hash /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool CacheDB::GetSHA256(bool const &GenOnly)
-{
- // Try to read the control information out of the DB.
- if ((CurStat.Flags & FlSHA256) == FlSHA256)
- {
- if (GenOnly == true)
- return true;
-
- SHA256Res = bytes2hex(CurStat.SHA256, sizeof(CurStat.SHA256));
- return true;
+ HashStringList hl = hashes.GetHashStringList();
+ for (HashStringList::const_iterator hs = hl.begin(); hs != hl.end(); ++hs)
+ {
+ HashesList.push_back(*hs);
+ if (strcasecmp(hs->HashType().c_str(), "SHA512") == 0)
+ {
+ Stats.SHA512Bytes += CurStat.FileSize;
+ hex2bytes(CurStat.SHA512, hs->HashValue().data(), sizeof(CurStat.SHA512));
+ CurStat.Flags |= FlSHA512;
+ }
+ else if (strcasecmp(hs->HashType().c_str(), "SHA256") == 0)
+ {
+ Stats.SHA256Bytes += CurStat.FileSize;
+ hex2bytes(CurStat.SHA256, hs->HashValue().data(), sizeof(CurStat.SHA256));
+ CurStat.Flags |= FlSHA256;
+ }
+ else if (strcasecmp(hs->HashType().c_str(), "SHA1") == 0)
+ {
+ Stats.SHA1Bytes += CurStat.FileSize;
+ hex2bytes(CurStat.SHA1, hs->HashValue().data(), sizeof(CurStat.SHA1));
+ CurStat.Flags |= FlSHA1;
+ }
+ else if (strcasecmp(hs->HashType().c_str(), "MD5Sum") == 0)
+ {
+ Stats.MD5Bytes += CurStat.FileSize;
+ hex2bytes(CurStat.MD5, hs->HashValue().data(), sizeof(CurStat.MD5));
+ CurStat.Flags |= FlMD5;
+ }
+ else
+ return _error->Error("Got unknown unrequested hashtype %s", hs->HashType().c_str());
+ }
}
-
- Stats.SHA256Bytes += CurStat.FileSize;
-
- if (OpenFile() == false)
- return false;
-
- SHA256Summation SHA256;
- if (Fd->Seek(0) == false || SHA256.AddFD(*Fd, CurStat.FileSize) == false)
- return false;
-
- SHA256Res = SHA256.Result();
- hex2bytes(CurStat.SHA256, SHA256Res.data(), sizeof(CurStat.SHA256));
- CurStat.Flags |= FlSHA256;
- return true;
-}
- /*}}}*/
-// CacheDB::GetSHA256 - Get the SHA256 hash /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool CacheDB::GetSHA512(bool const &GenOnly)
-{
- // Try to read the control information out of the DB.
- if ((CurStat.Flags & FlSHA512) == FlSHA512)
- {
- if (GenOnly == true)
- return true;
-
- SHA512Res = bytes2hex(CurStat.SHA512, sizeof(CurStat.SHA512));
+ if (GenOnly == true)
return true;
- }
-
- Stats.SHA512Bytes += CurStat.FileSize;
-
- if (OpenFile() == false)
- return false;
- SHA512Summation SHA512;
- if (Fd->Seek(0) == false || SHA512.AddFD(*Fd, CurStat.FileSize) == false)
- return false;
-
- SHA512Res = SHA512.Result();
- hex2bytes(CurStat.SHA512, SHA512Res.data(), sizeof(CurStat.SHA512));
- CurStat.Flags |= FlSHA512;
- return true;
+ return HashesList.push_back(HashString("MD5Sum", bytes2hex(CurStat.MD5, sizeof(CurStat.MD5)))) &&
+ HashesList.push_back(HashString("SHA1", bytes2hex(CurStat.SHA1, sizeof(CurStat.SHA1)))) &&
+ HashesList.push_back(HashString("SHA256", bytes2hex(CurStat.SHA256, sizeof(CurStat.SHA256)))) &&
+ HashesList.push_back(HashString("SHA512", bytes2hex(CurStat.SHA512, sizeof(CurStat.SHA512))));
}
/*}}}*/
// CacheDB::Finish - Write back the cache structure /*{{{*/
diff --git a/ftparchive/cachedb.h b/ftparchive/cachedb.h
index 54a274944..14dba5578 100644
--- a/ftparchive/cachedb.h
+++ b/ftparchive/cachedb.h
@@ -12,6 +12,7 @@
#ifndef CACHEDB_H
#define CACHEDB_H
+#include <apt-pkg/hashes.h>
#include <apt-pkg/debfile.h>
#include <db.h>
@@ -90,11 +91,8 @@ class CacheDB
bool LoadControl();
bool LoadContents(bool const &GenOnly);
bool LoadSource();
- bool GetMD5(bool const &GenOnly);
- bool GetSHA1(bool const &GenOnly);
- bool GetSHA256(bool const &GenOnly);
- bool GetSHA512(bool const &GenOnly);
-
+ bool GetHashes(bool const GenOnly, unsigned int const DoHashes);
+
// Stat info stored in the DB, Fixed types since it is written to disk.
enum FlagList {FlControl = (1<<0),FlMD5=(1<<1),FlContents=(1<<2),
FlSize=(1<<3), FlSHA1=(1<<4), FlSHA256=(1<<5),
@@ -124,12 +122,8 @@ class CacheDB
debDebFile::MemControlExtract Control;
ContentsExtract Contents;
DscExtract Dsc;
+ HashStringList HashesList;
- std::string MD5Res;
- std::string SHA1Res;
- std::string SHA256Res;
- std::string SHA512Res;
-
// Runtime statistics
struct Stats
{
@@ -165,16 +159,13 @@ class CacheDB
bool SetFile(std::string const &FileName,struct stat St,FileFd *Fd);
// terrible old overloaded interface
- bool GetFileInfo(std::string const &FileName,
- bool const &DoControl,
- bool const &DoContents,
- bool const &GenContentsOnly,
- bool const &DoSource,
- bool const &DoMD5,
- bool const &DoSHA1,
- bool const &DoSHA256,
- bool const &DoSHA512,
- bool const &checkMtime = false);
+ bool GetFileInfo(std::string const &FileName,
+ bool const &DoControl,
+ bool const &DoContents,
+ bool const &GenContentsOnly,
+ bool const DoSource,
+ unsigned int const DoHashes,
+ bool const &checkMtime = false);
bool Finish();
diff --git a/ftparchive/writer.cc b/ftparchive/writer.cc
index 7c1c9cc03..db617e92a 100644
--- a/ftparchive/writer.cc
+++ b/ftparchive/writer.cc
@@ -54,29 +54,42 @@ FTWScanner *FTWScanner::Owner;
// SetTFRewriteData - Helper for setting rewrite lists /*{{{*/
// ---------------------------------------------------------------------
/* */
-inline void SetTFRewriteData(struct TFRewriteData &tfrd,
- const char *tag,
+static inline TFRewriteData SetTFRewriteData(const char *tag,
const char *rewrite,
const char *newtag = 0)
{
- tfrd.Tag = tag;
- tfrd.Rewrite = rewrite;
- tfrd.NewTag = newtag;
+ TFRewriteData tfrd;
+ tfrd.Tag = tag;
+ tfrd.Rewrite = rewrite;
+ tfrd.NewTag = newtag;
+ return tfrd;
+}
+ /*}}}*/
+// ConfigToDoHashes - which hashes to generate /*{{{*/
+static void SingleConfigToDoHashes(unsigned int &DoHashes, std::string const &Conf, unsigned int const Flag)
+{
+ if (_config->FindB(Conf, true) == true)
+ DoHashes |= Flag;
+ else
+ DoHashes &= ~Flag;
+}
+static void ConfigToDoHashes(unsigned int &DoHashes, std::string const &Conf)
+{
+ SingleConfigToDoHashes(DoHashes, Conf + "::MD5", Hashes::MD5SUM);
+ SingleConfigToDoHashes(DoHashes, Conf + "::SHA1", Hashes::SHA1SUM);
+ SingleConfigToDoHashes(DoHashes, Conf + "::SHA256", Hashes::SHA256SUM);
+ SingleConfigToDoHashes(DoHashes, Conf + "::SHA512", Hashes::SHA512SUM);
}
/*}}}*/
// FTWScanner::FTWScanner - Constructor /*{{{*/
// ---------------------------------------------------------------------
/* */
-FTWScanner::FTWScanner(string const &Arch): Arch(Arch)
+FTWScanner::FTWScanner(string const &Arch): Arch(Arch), DoHashes(~0)
{
ErrorPrinted = false;
NoLinkAct = !_config->FindB("APT::FTPArchive::DeLinkAct",true);
-
- DoMD5 = _config->FindB("APT::FTPArchive::MD5",true);
- DoSHA1 = _config->FindB("APT::FTPArchive::SHA1",true);
- DoSHA256 = _config->FindB("APT::FTPArchive::SHA256",true);
- DoSHA512 = _config->FindB("APT::FTPArchive::SHA512",true);
+ ConfigToDoHashes(DoHashes, "APT::FTPArchive");
}
/*}}}*/
// FTWScanner::Scanner - FTW Scanner /*{{{*/
@@ -327,10 +340,7 @@ PackagesWriter::PackagesWriter(string const &DB,string const &Overrides,string c
DeLinkLimit = 0;
// Process the command line options
- DoMD5 = _config->FindB("APT::FTPArchive::Packages::MD5",DoMD5);
- DoSHA1 = _config->FindB("APT::FTPArchive::Packages::SHA1",DoSHA1);
- DoSHA256 = _config->FindB("APT::FTPArchive::Packages::SHA256",DoSHA256);
- DoSHA512 = _config->FindB("APT::FTPArchive::Packages::SHA512",DoSHA512);
+ ConfigToDoHashes(DoHashes, "APT::FTPArchive::Packages");
DoAlwaysStat = _config->FindB("APT::FTPArchive::AlwaysStat", false);
DoContents = _config->FindB("APT::FTPArchive::Contents",true);
NoOverride = _config->FindB("APT::FTPArchive::NoOverrideMsg",false);
@@ -385,12 +395,12 @@ bool FTWScanner::SetExts(string const &Vals)
bool PackagesWriter::DoPackage(string FileName)
{
// Pull all the data we need form the DB
- if (Db.GetFileInfo(FileName,
- true, /* DoControl */
- DoContents,
- true, /* GenContentsOnly */
- false, /* DoSource */
- DoMD5, DoSHA1, DoSHA256, DoSHA512, DoAlwaysStat) == false)
+ if (Db.GetFileInfo(FileName,
+ true, /* DoControl */
+ DoContents,
+ true, /* GenContentsOnly */
+ false, /* DoSource */
+ DoHashes, DoAlwaysStat) == false)
{
return false;
}
@@ -454,30 +464,27 @@ bool PackagesWriter::DoPackage(string FileName)
}
// This lists all the changes to the fields we are going to make.
- // (7 hardcoded + maintainer + suggests + end marker)
- TFRewriteData Changes[6+2+OverItem->FieldOverride.size()+1+1];
-
- unsigned int End = 0;
- SetTFRewriteData(Changes[End++], "Size", Size);
- if (DoMD5 == true)
- SetTFRewriteData(Changes[End++], "MD5sum", Db.MD5Res.c_str());
- if (DoSHA1 == true)
- SetTFRewriteData(Changes[End++], "SHA1", Db.SHA1Res.c_str());
- if (DoSHA256 == true)
- SetTFRewriteData(Changes[End++], "SHA256", Db.SHA256Res.c_str());
- if (DoSHA512 == true)
- SetTFRewriteData(Changes[End++], "SHA512", Db.SHA512Res.c_str());
- SetTFRewriteData(Changes[End++], "Filename", NewFileName.c_str());
- SetTFRewriteData(Changes[End++], "Priority", OverItem->Priority.c_str());
- SetTFRewriteData(Changes[End++], "Status", 0);
- SetTFRewriteData(Changes[End++], "Optional", 0);
+ std::vector<TFRewriteData> Changes;
+
+ Changes.push_back(SetTFRewriteData("Size", Size));
+ for (HashStringList::const_iterator hs = Db.HashesList.begin(); hs != Db.HashesList.end(); ++hs)
+ {
+ if (hs->HashType() == "MD5Sum")
+ Changes.push_back(SetTFRewriteData("MD5sum", hs->HashValue().c_str()));
+ else
+ Changes.push_back(SetTFRewriteData(hs->HashType().c_str(), hs->HashValue().c_str()));
+ }
+ Changes.push_back(SetTFRewriteData("Filename", NewFileName.c_str()));
+ Changes.push_back(SetTFRewriteData("Priority", OverItem->Priority.c_str()));
+ Changes.push_back(SetTFRewriteData("Status", 0));
+ Changes.push_back(SetTFRewriteData("Optional", 0));
string DescriptionMd5;
if (LongDescription == false) {
MD5Summation descmd5;
descmd5.Add(desc.c_str());
DescriptionMd5 = descmd5.Result().Value();
- SetTFRewriteData(Changes[End++], "Description-md5", DescriptionMd5.c_str());
+ Changes.push_back(SetTFRewriteData("Description-md5", DescriptionMd5.c_str()));
if (TransWriter != NULL)
TransWriter->DoPackage(Package, desc, DescriptionMd5);
}
@@ -492,12 +499,12 @@ bool PackagesWriter::DoPackage(string FileName)
NewLine(1);
ioprintf(c1out, _(" %s maintainer is %s not %s\n"),
Package.c_str(), Tags.FindS("Maintainer").c_str(), OverItem->OldMaint.c_str());
- }
+ }
}
-
+
if (NewMaint.empty() == false)
- SetTFRewriteData(Changes[End++], "Maintainer", NewMaint.c_str());
-
+ Changes.push_back(SetTFRewriteData("Maintainer", NewMaint.c_str()));
+
/* Get rid of the Optional tag. This is an ugly, ugly, ugly hack that
dpkg-scanpackages does. Well sort of. dpkg-scanpackages just does renaming
but dpkg does this append bit. So we do the append bit, at least that way the
@@ -508,17 +515,17 @@ bool PackagesWriter::DoPackage(string FileName)
{
if (Tags.FindS("Suggests").empty() == false)
OptionalStr = Tags.FindS("Suggests") + ", " + OptionalStr;
- SetTFRewriteData(Changes[End++], "Suggests", OptionalStr.c_str());
+ Changes.push_back(SetTFRewriteData("Suggests", OptionalStr.c_str()));
}
- for (map<string,string>::const_iterator I = OverItem->FieldOverride.begin();
+ for (map<string,string>::const_iterator I = OverItem->FieldOverride.begin();
I != OverItem->FieldOverride.end(); ++I)
- SetTFRewriteData(Changes[End++],I->first.c_str(),I->second.c_str());
+ Changes.push_back(SetTFRewriteData(I->first.c_str(),I->second.c_str()));
- SetTFRewriteData(Changes[End++], 0, 0);
+ Changes.push_back(SetTFRewriteData( 0, 0));
// Rewrite and store the fields.
- if (TFRewrite(Output,Tags,TFRewritePackageOrder,Changes) == false)
+ if (TFRewrite(Output,Tags,TFRewritePackageOrder,Changes.data()) == false)
return false;
fprintf(Output,"\n");
@@ -589,10 +596,7 @@ SourcesWriter::SourcesWriter(string const &DB, string const &BOverrides,string c
BufSize = 0;
// Process the command line options
- DoMD5 = _config->FindB("APT::FTPArchive::Sources::MD5",DoMD5);
- DoSHA1 = _config->FindB("APT::FTPArchive::Sources::SHA1",DoSHA1);
- DoSHA256 = _config->FindB("APT::FTPArchive::Sources::SHA256",DoSHA256);
- DoSHA512 = _config->FindB("APT::FTPArchive::Sources::SHA512",DoSHA512);
+ ConfigToDoHashes(DoHashes, "APT::FTPArchive::Sources");
NoOverride = _config->FindB("APT::FTPArchive::NoOverrideMsg",false);
DoAlwaysStat = _config->FindB("APT::FTPArchive::AlwaysStat", false);
@@ -614,17 +618,25 @@ SourcesWriter::SourcesWriter(string const &DB, string const &BOverrides,string c
}
/*}}}*/
// SourcesWriter::DoPackage - Process a single package /*{{{*/
-// ---------------------------------------------------------------------
-/* */
+static std::ostream& addDscHash(std::ostream &out, unsigned int const DoHashes,
+ Hashes::SupportedHashes const DoIt, pkgTagSection &Tags, char const * const FieldName,
+ HashString const * const Hash, unsigned long long Size, std::string FileName)
+{
+ if ((DoHashes & DoIt) != DoIt || Tags.Exists(FieldName) == false || Hash == NULL)
+ return out;
+ out << "\n " << Hash->HashValue() << " " << Size << " " << FileName
+ << "\n " << Tags.FindS(FieldName);
+ return out;
+}
bool SourcesWriter::DoPackage(string FileName)
{
// Pull all the data we need form the DB
if (Db.GetFileInfo(FileName,
- false, /* DoControl */
- false, /* DoContents */
- false, /* GenContentsOnly */
- true, /* DoSource */
- DoMD5, DoSHA1, DoSHA256, DoSHA512, DoAlwaysStat) == false)
+ false, /* DoControl */
+ false, /* DoContents */
+ false, /* GenContentsOnly */
+ true, /* DoSource */
+ DoHashes, DoAlwaysStat) == false)
{
return false;
}
@@ -712,29 +724,19 @@ bool SourcesWriter::DoPackage(string FileName)
*SOverItem = *OverItem;
}
}
-
+
// Add the dsc to the files hash list
string const strippedName = flNotDir(FileName);
std::ostringstream ostreamFiles;
- if (DoMD5 == true && Tags.Exists("Files"))
- ostreamFiles << "\n " << Db.MD5Res.c_str() << " " << St.st_size << " "
- << strippedName << "\n " << Tags.FindS("Files");
+ addDscHash(ostreamFiles, DoHashes, Hashes::MD5SUM, Tags, "Files", Db.HashesList.find("MD5Sum"), St.st_size, strippedName);
string const Files = ostreamFiles.str();
std::ostringstream ostreamSha1;
- if (DoSHA1 == true && Tags.Exists("Checksums-Sha1"))
- ostreamSha1 << "\n " << string(Db.SHA1Res.c_str()) << " " << St.st_size << " "
- << strippedName << "\n " << Tags.FindS("Checksums-Sha1");
-
+ addDscHash(ostreamSha1, DoHashes, Hashes::SHA1SUM, Tags, "Checksums-Sha1", Db.HashesList.find("SHA1"), St.st_size, strippedName);
std::ostringstream ostreamSha256;
- if (DoSHA256 == true && Tags.Exists("Checksums-Sha256"))
- ostreamSha256 << "\n " << string(Db.SHA256Res.c_str()) << " " << St.st_size << " "
- << strippedName << "\n " << Tags.FindS("Checksums-Sha256");
-
+ addDscHash(ostreamSha256, DoHashes, Hashes::SHA256SUM, Tags, "Checksums-Sha256", Db.HashesList.find("SHA256"), St.st_size, strippedName);
std::ostringstream ostreamSha512;
- if (DoSHA512 == true && Tags.Exists("Checksums-Sha512"))
- ostreamSha512 << "\n " << string(Db.SHA512Res.c_str()) << " " << St.st_size << " "
- << strippedName << "\n " << Tags.FindS("Checksums-Sha512");
+ addDscHash(ostreamSha512, DoHashes, Hashes::SHA512SUM, Tags, "Checksums-Sha512", Db.HashesList.find("SHA512"), St.st_size, strippedName);
// Strip the DirStrip prefix from the FileName and add the PathPrefix
string NewFileName;
@@ -766,35 +768,54 @@ bool SourcesWriter::DoPackage(string FileName)
string OriginalPath = Directory + ParseJnk;
// Add missing hashes to source files
- if ((DoSHA1 == true && !Tags.Exists("Checksums-Sha1")) ||
- (DoSHA256 == true && !Tags.Exists("Checksums-Sha256")) ||
- (DoSHA512 == true && !Tags.Exists("Checksums-Sha512")))
+ if (((DoHashes & Hashes::SHA1SUM) == Hashes::SHA1SUM && !Tags.Exists("Checksums-Sha1")) ||
+ ((DoHashes & Hashes::SHA256SUM) == Hashes::SHA256SUM && !Tags.Exists("Checksums-Sha256")) ||
+ ((DoHashes & Hashes::SHA512SUM) == Hashes::SHA512SUM && !Tags.Exists("Checksums-Sha512")))
{
- if (Db.GetFileInfo(OriginalPath,
+ if (Db.GetFileInfo(OriginalPath,
false, /* DoControl */
false, /* DoContents */
false, /* GenContentsOnly */
false, /* DoSource */
- DoMD5, DoSHA1, DoSHA256, DoSHA512,
+ DoHashes,
DoAlwaysStat) == false)
{
return _error->Error("Error getting file info");
}
- if (DoSHA1 == true && !Tags.Exists("Checksums-Sha1"))
- ostreamSha1 << "\n " << string(Db.SHA1Res) << " "
- << Db.GetFileSize() << " " << ParseJnk;
-
- if (DoSHA256 == true && !Tags.Exists("Checksums-Sha256"))
- ostreamSha256 << "\n " << string(Db.SHA256Res) << " "
- << Db.GetFileSize() << " " << ParseJnk;
-
- if (DoSHA512 == true && !Tags.Exists("Checksums-Sha512"))
- ostreamSha512 << "\n " << string(Db.SHA512Res) << " "
- << Db.GetFileSize() << " " << ParseJnk;
+ for (HashStringList::const_iterator hs = Db.HashesList.begin(); hs != Db.HashesList.end(); ++hs)
+ {
+ if (hs->HashType() == "MD5Sum")
+ continue;
+ char const * fieldname;
+ std::ostream * out;
+ if (hs->HashType() == "SHA1")
+ {
+ fieldname = "Checksums-Sha1";
+ out = &ostreamSha1;
+ }
+ else if (hs->HashType() == "SHA256")
+ {
+ fieldname = "Checksums-Sha256";
+ out = &ostreamSha256;
+ }
+ else if (hs->HashType() == "SHA512")
+ {
+ fieldname = "Checksums-Sha512";
+ out = &ostreamSha512;
+ }
+ else
+ {
+ _error->Warning("Ignoring unknown Checksumtype %s in SourcesWriter::DoPackages", hs->HashType().c_str());
+ continue;
+ }
+ if (Tags.Exists(fieldname) == true)
+ continue;
+ (*out) << "\n " << hs->HashValue() << " " << Db.GetFileSize() << " " << ParseJnk;
+ }
- // write back the GetFileInfo() stats data
- Db.Finish();
+ // write back the GetFileInfo() stats data
+ Db.Finish();
}
// Perform the delinking operation
@@ -820,22 +841,21 @@ bool SourcesWriter::DoPackage(string FileName)
// This lists all the changes to the fields we are going to make.
// (5 hardcoded + checksums + maintainer + end marker)
- TFRewriteData Changes[5+2+1+SOverItem->FieldOverride.size()+1];
+ std::vector<TFRewriteData> Changes;
- unsigned int End = 0;
- SetTFRewriteData(Changes[End++],"Source",Package.c_str(),"Package");
+ Changes.push_back(SetTFRewriteData("Source",Package.c_str(),"Package"));
if (Files.empty() == false)
- SetTFRewriteData(Changes[End++],"Files",Files.c_str());
+ Changes.push_back(SetTFRewriteData("Files",Files.c_str()));
if (ChecksumsSha1.empty() == false)
- SetTFRewriteData(Changes[End++],"Checksums-Sha1",ChecksumsSha1.c_str());
+ Changes.push_back(SetTFRewriteData("Checksums-Sha1",ChecksumsSha1.c_str()));
if (ChecksumsSha256.empty() == false)
- SetTFRewriteData(Changes[End++],"Checksums-Sha256",ChecksumsSha256.c_str());
+ Changes.push_back(SetTFRewriteData("Checksums-Sha256",ChecksumsSha256.c_str()));
if (ChecksumsSha512.empty() == false)
- SetTFRewriteData(Changes[End++],"Checksums-Sha512",ChecksumsSha512.c_str());
+ Changes.push_back(SetTFRewriteData("Checksums-Sha512",ChecksumsSha512.c_str()));
if (Directory != "./")
- SetTFRewriteData(Changes[End++],"Directory",Directory.c_str());
- SetTFRewriteData(Changes[End++],"Priority",BestPrio.c_str());
- SetTFRewriteData(Changes[End++],"Status",0);
+ Changes.push_back(SetTFRewriteData("Directory",Directory.c_str()));
+ Changes.push_back(SetTFRewriteData("Priority",BestPrio.c_str()));
+ Changes.push_back(SetTFRewriteData("Status",0));
// Rewrite the maintainer field if necessary
bool MaintFailed;
@@ -850,16 +870,16 @@ bool SourcesWriter::DoPackage(string FileName)
}
}
if (NewMaint.empty() == false)
- SetTFRewriteData(Changes[End++], "Maintainer", NewMaint.c_str());
+ Changes.push_back(SetTFRewriteData("Maintainer", NewMaint.c_str()));
for (map<string,string>::const_iterator I = SOverItem->FieldOverride.begin();
I != SOverItem->FieldOverride.end(); ++I)
- SetTFRewriteData(Changes[End++],I->first.c_str(),I->second.c_str());
+ Changes.push_back(SetTFRewriteData(I->first.c_str(),I->second.c_str()));
- SetTFRewriteData(Changes[End++], 0, 0);
+ Changes.push_back(SetTFRewriteData(0, 0));
// Rewrite and store the fields.
- if (TFRewrite(Output,Tags,TFRewriteSourceOrder,Changes) == false)
+ if (TFRewrite(Output,Tags,TFRewriteSourceOrder,Changes.data()) == false)
return false;
fprintf(Output,"\n");
@@ -886,15 +906,13 @@ ContentsWriter::ContentsWriter(string const &DB, string const &Arch) :
determine what the package name is. */
bool ContentsWriter::DoPackage(string FileName, string Package)
{
- if (!Db.GetFileInfo(FileName,
- Package.empty(), /* DoControl */
- true, /* DoContents */
- false, /* GenContentsOnly */
- false, /* DoSource */
- false, /* DoMD5 */
- false, /* DoSHA1 */
- false, /* DoSHA256 */
- false)) /* DoSHA512 */
+ if (!Db.GetFileInfo(FileName,
+ Package.empty(), /* DoControl */
+ true, /* DoContents */
+ false, /* GenContentsOnly */
+ false, /* DoSource */
+ 0, /* DoHashes */
+ false /* checkMtime */))
{
return false;
}
@@ -1030,9 +1048,7 @@ ReleaseWriter::ReleaseWriter(string const &/*DB*/)
fprintf(Output, "%s: %s\n", (*I).first.c_str(), Value.c_str());
}
- DoMD5 = _config->FindB("APT::FTPArchive::Release::MD5",DoMD5);
- DoSHA1 = _config->FindB("APT::FTPArchive::Release::SHA1",DoSHA1);
- DoSHA256 = _config->FindB("APT::FTPArchive::Release::SHA256",DoSHA256);
+ ConfigToDoHashes(DoHashes, "APT::FTPArchive::Release");
}
/*}}}*/
// ReleaseWriter::DoPackage - Process a single package /*{{{*/
@@ -1066,15 +1082,8 @@ bool ReleaseWriter::DoPackage(string FileName)
CheckSums[NewFileName].size = fd.Size();
Hashes hs;
- hs.AddFD(fd, 0, DoMD5, DoSHA1, DoSHA256, DoSHA512);
- if (DoMD5 == true)
- CheckSums[NewFileName].MD5 = hs.MD5.Result();
- if (DoSHA1 == true)
- CheckSums[NewFileName].SHA1 = hs.SHA1.Result();
- if (DoSHA256 == true)
- CheckSums[NewFileName].SHA256 = hs.SHA256.Result();
- if (DoSHA512 == true)
- CheckSums[NewFileName].SHA512 = hs.SHA512.Result();
+ hs.AddFD(fd, 0, DoHashes);
+ CheckSums[NewFileName].Hashes = hs.GetHashStringList();
fd.Close();
return true;
@@ -1083,54 +1092,29 @@ bool ReleaseWriter::DoPackage(string FileName)
/*}}}*/
// ReleaseWriter::Finish - Output the checksums /*{{{*/
// ---------------------------------------------------------------------
-void ReleaseWriter::Finish()
+static void printChecksumTypeRecord(FILE * const Output, char const * const Type, map<string, ReleaseWriter::CheckSum> const &CheckSums)
{
- if (DoMD5 == true)
- {
- fprintf(Output, "MD5Sum:\n");
- for(map<string,struct CheckSum>::const_iterator I = CheckSums.begin();
- I != CheckSums.end(); ++I)
- {
- fprintf(Output, " %s %16llu %s\n",
- (*I).second.MD5.c_str(),
- (*I).second.size,
- (*I).first.c_str());
- }
- }
- if (DoSHA1 == true)
- {
- fprintf(Output, "SHA1:\n");
- for(map<string,struct CheckSum>::const_iterator I = CheckSums.begin();
- I != CheckSums.end(); ++I)
- {
- fprintf(Output, " %s %16llu %s\n",
- (*I).second.SHA1.c_str(),
- (*I).second.size,
- (*I).first.c_str());
- }
- }
- if (DoSHA256 == true)
- {
- fprintf(Output, "SHA256:\n");
- for(map<string,struct CheckSum>::const_iterator I = CheckSums.begin();
+ fprintf(Output, "%s:\n", Type);
+ for(map<string,ReleaseWriter::CheckSum>::const_iterator I = CheckSums.begin();
I != CheckSums.end(); ++I)
{
+ HashString const * const hs = I->second.Hashes.find(Type);
+ if (hs == NULL)
+ continue;
fprintf(Output, " %s %16llu %s\n",
- (*I).second.SHA256.c_str(),
+ hs->HashValue().c_str(),
(*I).second.size,
(*I).first.c_str());
}
- }
-
- fprintf(Output, "SHA512:\n");
- for(map<string,struct CheckSum>::const_iterator I = CheckSums.begin();
- I != CheckSums.end();
- ++I)
- {
- fprintf(Output, " %s %16llu %s\n",
- (*I).second.SHA512.c_str(),
- (*I).second.size,
- (*I).first.c_str());
- }
-
+}
+void ReleaseWriter::Finish()
+{
+ if ((DoHashes & Hashes::MD5SUM) == Hashes::MD5SUM)
+ printChecksumTypeRecord(Output, "MD5Sum", CheckSums);
+ if ((DoHashes & Hashes::SHA1SUM) == Hashes::SHA1SUM)
+ printChecksumTypeRecord(Output, "SHA1", CheckSums);
+ if ((DoHashes & Hashes::SHA256SUM) == Hashes::SHA256SUM)
+ printChecksumTypeRecord(Output, "SHA256", CheckSums);
+ if ((DoHashes & Hashes::SHA512SUM) == Hashes::SHA512SUM)
+ printChecksumTypeRecord(Output, "SHA512", CheckSums);
}
diff --git a/ftparchive/writer.h b/ftparchive/writer.h
index b1a653e7d..c62d4addf 100644
--- a/ftparchive/writer.h
+++ b/ftparchive/writer.h
@@ -13,6 +13,8 @@
#ifndef WRITER_H
#define WRITER_H
+#include <apt-pkg/hashes.h>
+
#include <string>
#include <stdio.h>
#include <iostream>
@@ -61,10 +63,7 @@ class FTWScanner
}
public:
- bool DoMD5;
- bool DoSHA1;
- bool DoSHA256;
- bool DoSHA512;
+ unsigned int DoHashes;
unsigned long DeLinkLimit;
string InternalPrefix;
@@ -195,17 +194,14 @@ public:
string PathPrefix;
string DirStrip;
-protected:
struct CheckSum
{
- string MD5;
- string SHA1;
- string SHA256;
- string SHA512;
+ HashStringList Hashes;
// Limited by FileFd::Size()
unsigned long long size;
~CheckSum() {};
};
+protected:
map<string,struct CheckSum> CheckSums;
};
diff --git a/methods/server.cc b/methods/server.cc
index 5a13f18a7..c91d3b218 100644
--- a/methods/server.cc
+++ b/methods/server.cc
@@ -392,9 +392,16 @@ bool ServerMethod::Fetch(FetchItem *)
for (FetchItem *I = Queue; I != 0 && Depth < (signed)PipelineDepth;
I = I->Next, Depth++)
{
- // If pipelining is disabled, we only queue 1 request
- if (Server->Pipeline == false && Depth >= 0)
- break;
+ if (Depth >= 0)
+ {
+ // If pipelining is disabled, we only queue 1 request
+ if (Server->Pipeline == false)
+ break;
+ // if we have no hashes, do at most one such request
+ // as we can't fixup pipeling misbehaviors otherwise
+ else if (I->ExpectedHashes.usable() == false)
+ break;
+ }
// Make sure we stick with the same server
if (Server->Comp(I->Uri) == false)
@@ -546,7 +553,38 @@ int ServerMethod::Loop()
// Send status to APT
if (Result == true)
{
- Res.TakeHashes(*Server->GetHashes());
+ Hashes * const resultHashes = Server->GetHashes();
+ HashStringList const hashList = resultHashes->GetHashStringList();
+ if (PipelineDepth != 0 && Queue->ExpectedHashes.usable() == true && Queue->ExpectedHashes != hashList)
+ {
+ // we did not get the expected hash… mhhh:
+ // could it be that server/proxy messed up pipelining?
+ FetchItem * BeforeI = Queue;
+ for (FetchItem *I = Queue->Next; I != 0 && I != QueueBack; I = I->Next)
+ {
+ if (I->ExpectedHashes.usable() == true && I->ExpectedHashes == hashList)
+ {
+ // yes, he did! Disable pipelining and rewrite queue
+ if (Server->Pipeline == true)
+ {
+ // FIXME: fake a warning message as we have no proper way of communicating here
+ std::string out;
+ strprintf(out, _("Automatically disabled %s due to incorrect response from server/proxy. (man 5 apt.conf)"), "Acquire::http::PipelineDepth");
+ std::cerr << "W: " << out << std::endl;
+ Server->Pipeline = false;
+ // we keep the PipelineDepth value so that the rest of the queue can be fixed up as well
+ }
+ Rename(Res.Filename, I->DestFile);
+ Res.Filename = I->DestFile;
+ BeforeI->Next = I->Next;
+ I->Next = Queue;
+ Queue = I;
+ break;
+ }
+ BeforeI = I;
+ }
+ }
+ Res.TakeHashes(*resultHashes);
URIDone(Res);
}
else
diff --git a/methods/server.h b/methods/server.h
index 0f45ab994..5299b3954 100644
--- a/methods/server.h
+++ b/methods/server.h
@@ -140,7 +140,7 @@ class ServerMethod : public pkgAcqMethod
virtual ServerState * CreateServerState(URI uri) = 0;
virtual void RotateDNS() = 0;
- ServerMethod(const char *Ver,unsigned long Flags = 0) : pkgAcqMethod(Ver, Flags), Server(NULL), File(NULL), PipelineDepth(0), AllowRedirect(false), Debug(false) {};
+ ServerMethod(const char *Ver,unsigned long Flags = 0) : pkgAcqMethod(Ver, Flags), Server(NULL), File(NULL), PipelineDepth(10), AllowRedirect(false), Debug(false) {};
virtual ~ServerMethod() {};
};
diff --git a/test/integration/framework b/test/integration/framework
index ab1274d9c..b469fd3f6 100644
--- a/test/integration/framework
+++ b/test/integration/framework
@@ -36,7 +36,7 @@ msgndebug() { echo -n "${CDEBUG}D: $1${CNORMAL}"; }
msgtest() {
while [ -n "$1" ]; do
echo -n "${CINFO}$1${CCMD} "
- echo -n "$(echo "$2" | sed -e 's/^aptc/apt-c/' -e 's/^aptg/apt-g/' -e 's/^aptf/apt-f/')${CINFO} "
+ echo -n "$(echo "$2" | sed -e 's#^apt\([cgfs]\)#apt-\1#')${CINFO} "
shift
if [ -n "$1" ]; then shift; else break; fi
done
@@ -102,10 +102,10 @@ runapt() {
local CMD="$1"
shift
case $CMD in
- sh|aptitude|*/*) ;;
+ sh|aptitude|*/*|command) ;;
*) CMD="${BUILDDIRECTORY}/$CMD";;
esac
- MALLOC_PERTURB_=21 MALLOC_CHECK_=2 APT_CONFIG="$(getaptconfig)" LD_LIBRARY_PATH=${BUILDDIRECTORY} $CMD "$@"
+ MALLOC_PERTURB_=21 MALLOC_CHECK_=2 APT_CONFIG="$(getaptconfig)" LD_LIBRARY_PATH=${LIBRARYPATH} $CMD "$@"
}
aptconfig() { runapt apt-config "$@"; }
aptcache() { runapt apt-cache "$@"; }
@@ -114,6 +114,7 @@ aptget() { runapt apt-get "$@"; }
aptftparchive() { runapt apt-ftparchive "$@"; }
aptkey() { runapt apt-key "$@"; }
aptmark() { runapt apt-mark "$@"; }
+aptsortpkgs() { runapt apt-sortpkgs "$@"; }
apt() { runapt apt "$@"; }
apthelper() { runapt "${APTHELPERBINDIR}/apt-helper" "$@"; }
aptwebserver() { runapt "${APTWEBSERVERBINDIR}/aptwebserver" "$@"; }
@@ -127,11 +128,9 @@ dpkgcheckbuilddeps() {
command dpkg-checkbuilddeps --admindir=${TMPWORKINGDIRECTORY}/rootdir/var/lib/dpkg "$@"
}
gdb() {
- echo "gdb: run »$*«"
- CMD="$1"
+ local CMD="$1"
shift
-
- APT_CONFIG=aptconfig.conf LD_LIBRARY_PATH=${LIBRARYPATH} command gdb ${BUILDDIRECTORY}/$CMD --args ${BUILDDIRECTORY}/$CMD "$@"
+ runapt command gdb --quiet -ex run "${BUILDDIRECTORY}/$CMD" --args "${BUILDDIRECTORY}/$CMD" "$@"
}
gpg() {
# see apt-key for the whole trickery. Setup is done in setupenvironment
@@ -226,6 +225,7 @@ setupenvironment() {
fi
echo "DPKG::options:: \"--log=${TMPWORKINGDIRECTORY}/rootdir/var/log/dpkg.log\";" >> aptconfig.conf
echo 'quiet::NoUpdate "true";' >> aptconfig.conf
+ echo 'quiet::NoStatistic "true";' >> aptconfig.conf
echo "Acquire::https::CaInfo \"${TESTDIR}/apt.pem\";" > rootdir/etc/apt/apt.conf.d/99https
echo "Apt::Cmd::Disable-Script-Warning \"1\";" > rootdir/etc/apt/apt.conf.d/apt-binary
configcompression '.' 'gz' #'bz2' 'lzma' 'xz'
diff --git a/test/integration/test-apt-ftparchive-cachedb b/test/integration/test-apt-ftparchive-cachedb
index 147272a2c..0e1986bcd 100755
--- a/test/integration/test-apt-ftparchive-cachedb
+++ b/test/integration/test-apt-ftparchive-cachedb
@@ -5,7 +5,7 @@ ensure_correct_packages_file() {
testequal "Package: foo
Priority: optional
Section: others
-Installed-Size: 29
+$(dpkg-deb -I ./aptarchive/pool/main/foo_1_i386.deb | grep 'Installed-Size:' | sed 's#^ ##')
Maintainer: Joe Sixpack <joe@example.org>
Architecture: i386
Version: 1
@@ -25,7 +25,7 @@ usr/share/doc/foo/copyright others/foo" cat ./aptarchive/dists/test/Conte
TESTDIR=$(readlink -f $(dirname $0))
. $TESTDIR/framework
setupenvironment
-configarchitecture "i386"
+configarchitecture 'i386'
mkdir -p aptarchive/dists/test/main/i18n/
mkdir -p aptarchive/dists/test/main/source/
diff --git a/test/integration/test-apt-ftparchive-src-cachedb b/test/integration/test-apt-ftparchive-src-cachedb
index 1af193632..e7b148530 100755
--- a/test/integration/test-apt-ftparchive-src-cachedb
+++ b/test/integration/test-apt-ftparchive-src-cachedb
@@ -3,9 +3,9 @@ set -e
assert_correct_sources_file() {
testequal "Package: bar
-Binary: bar
-Version: 1.0
Architecture: all
+Version: 1.0
+Binary: bar
Format: 3.0 (native)
Directory: pool/main
Files:
@@ -24,9 +24,9 @@ Checksums-Sha512:
cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e 0 bar_1.0.tar.gz
Package: foo
-Binary: foo
-Version: 1.0
Architecture: all
+Version: 1.0
+Binary: foo
Format: 3.0 (native)
Directory: pool/main
Files:
@@ -43,7 +43,7 @@ Checksums-Sha256:
Checksums-Sha512:
3da0240fd764657c2f3661b4d750578a9a99b0580591b133756379d48117ebda87a5ed2467f513200d6e7eaf51422cbe91c15720eef7fb4bba2cc8ff81ebc547 171 foo_1.0.dsc
cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e 0 foo_1.0.tar.gz
-" cat ./aptarchive/dists/test/main/source/Sources
+" aptsortpkgs ./aptarchive/dists/test/main/source/Sources
}
create_source_files() {
@@ -177,6 +177,11 @@ assert_correct_sources_file
mkdir aptarchive/pool/invalid
printf "meep" > aptarchive/pool/invalid/invalid_1.0.dsc
testequal "
+E: Could not find a record in the DSC 'aptarchive/pool/invalid/invalid_1.0.dsc'" aptftparchive sources aptarchive/pool/invalid
+rm -f aptarchive/pool/invalid/invalid_1.0.dsc
+
+printf "meep: yes" > aptarchive/pool/invalid/invalid_1.0.dsc
+testequal "
E: Could not find a Source entry in the DSC 'aptarchive/pool/invalid/invalid_1.0.dsc'" aptftparchive sources aptarchive/pool/invalid
rm -f aptarchive/pool/invalid/invalid_1.0.dsc
diff --git a/test/integration/test-apt-sources-deb822 b/test/integration/test-apt-sources-deb822
index 5f54b7531..d8b2334ad 100755
--- a/test/integration/test-apt-sources-deb822
+++ b/test/integration/test-apt-sources-deb822
@@ -23,14 +23,14 @@ Description: summay
msgtest 'Test sources.list' 'old style'
echo "deb http://ftp.debian.org/debian stable main" > $SOURCES
-testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 :
-'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 :
+testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0
+'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0
'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 " aptget update --print-uris
msgtest 'Test sources.list' 'simple deb822'
echo "$BASE" > $SOURCES
-testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 :
-'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 :
+testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0
+'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0
'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 " aptget update --print-uris
@@ -39,29 +39,29 @@ msgtest 'Test deb822 with' 'two entries'
echo "$BASE" > $SOURCES
echo "" >> $SOURCES
echo "$BASE" | sed s/stable/unstable/ >> $SOURCES
-testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 :
-'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 :
+testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0
+'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0
'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0
-'http://ftp.debian.org/debian/dists/unstable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_unstable_main_binary-i386_Packages 0 :
-'http://ftp.debian.org/debian/dists/unstable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_unstable_main_i18n_Translation-en 0 :
+'http://ftp.debian.org/debian/dists/unstable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_unstable_main_binary-i386_Packages 0
+'http://ftp.debian.org/debian/dists/unstable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_unstable_main_i18n_Translation-en 0
'http://ftp.debian.org/debian/dists/unstable/InRelease' ftp.debian.org_debian_dists_unstable_InRelease 0 " aptget update --print-uris
# two suite entries
msgtest 'Test deb822 with' 'two Suite entries'
echo "$BASE" | sed -e "s/stable/stable unstable/" > $SOURCES
-testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 :
-'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 :
+testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0
+'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0
'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0
-'http://ftp.debian.org/debian/dists/unstable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_unstable_main_binary-i386_Packages 0 :
-'http://ftp.debian.org/debian/dists/unstable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_unstable_main_i18n_Translation-en 0 :
+'http://ftp.debian.org/debian/dists/unstable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_unstable_main_binary-i386_Packages 0
+'http://ftp.debian.org/debian/dists/unstable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_unstable_main_i18n_Translation-en 0
'http://ftp.debian.org/debian/dists/unstable/InRelease' ftp.debian.org_debian_dists_unstable_InRelease 0 " aptget update --print-uris
msgtest 'Test deb822' 'architecture option'
echo "$BASE" > $SOURCES
echo "Architectures: amd64 armel" >> $SOURCES
-testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/main/binary-amd64/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-amd64_Packages 0 :
-'http://ftp.debian.org/debian/dists/stable/main/binary-armel/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-armel_Packages 0 :
-'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 :
+testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/main/binary-amd64/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-amd64_Packages 0
+'http://ftp.debian.org/debian/dists/stable/main/binary-armel/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-armel_Packages 0
+'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0
'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 " aptget update --print-uris
@@ -85,19 +85,19 @@ testempty aptget update --print-uris
# multiple URIs
msgtest 'Test deb822 sources.list file which has' 'Multiple URIs work'
echo "$BASE" | sed -e 's#http://ftp.debian.org/debian#http://ftp.debian.org/debian http://ftp.de.debian.org/debian#' > $SOURCES
-testequal --nomsg "'http://ftp.de.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.de.debian.org_debian_dists_stable_main_binary-i386_Packages 0 :
-'http://ftp.de.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.de.debian.org_debian_dists_stable_main_i18n_Translation-en 0 :
+testequal --nomsg "'http://ftp.de.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.de.debian.org_debian_dists_stable_main_binary-i386_Packages 0
+'http://ftp.de.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.de.debian.org_debian_dists_stable_main_i18n_Translation-en 0
'http://ftp.de.debian.org/debian/dists/stable/InRelease' ftp.de.debian.org_debian_dists_stable_InRelease 0
-'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 :
-'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 :
+'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0
+'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0
'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 " aptget update --print-uris
# multiple Type in one field
msgtest 'Test deb822 sources.list file which has' 'Multiple Types work'
echo "$BASE" | sed -e 's#Types: deb#Types: deb deb-src#' > $SOURCES
-testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/main/source/Sources.bz2' ftp.debian.org_debian_dists_stable_main_source_Sources 0 :
-'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 :
-'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 :
+testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/main/source/Sources.bz2' ftp.debian.org_debian_dists_stable_main_source_Sources 0
+'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0
+'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0
'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 " aptget update --print-uris
# a Suite
@@ -107,6 +107,6 @@ Types: deb
URIs: http://emacs.naquadah.org
Suites: stable/
EOF
-testequal --nomsg "'http://emacs.naquadah.org/stable/Packages.bz2' emacs.naquadah.org_stable_Packages 0 :
-'http://emacs.naquadah.org/stable/en.bz2' emacs.naquadah.org_stable_en 0 :
+testequal --nomsg "'http://emacs.naquadah.org/stable/Packages.bz2' emacs.naquadah.org_stable_Packages 0
+'http://emacs.naquadah.org/stable/en.bz2' emacs.naquadah.org_stable_en 0
'http://emacs.naquadah.org/stable/InRelease' emacs.naquadah.org_stable_InRelease 0 " aptget update --print-uris
diff --git a/test/integration/test-bug-595691-empty-and-broken-archive-files b/test/integration/test-bug-595691-empty-and-broken-archive-files
index a05ed5fa6..8da0a52d2 100755
--- a/test/integration/test-bug-595691-empty-and-broken-archive-files
+++ b/test/integration/test-bug-595691-empty-and-broken-archive-files
@@ -13,7 +13,7 @@ setupflataptarchive
testaptgetupdate() {
rm -rf rootdir/var/lib/apt
aptget update 2>> testaptgetupdate.diff >> testaptgetupdate.diff || true
- sed -i -e '/^Fetched / d' -e '/Ign / d' -e '/Release/ d' -e 's#Get:[0-9]\+ #Get: #' -e 's#\[[0-9]* [kMGTPY]*B\]#\[\]#' testaptgetupdate.diff
+ sed -i -e '/Ign / d' -e '/Release/ d' -e 's#Get:[0-9]\+ #Get: #' -e 's#\[[0-9]* [kMGTPY]*B\]#\[\]#' testaptgetupdate.diff
GIVEN="$1"
shift
msgtest "Test for correctness of" "apt-get update with $*"
diff --git a/test/integration/test-bug-712435-missing-descriptions b/test/integration/test-bug-712435-missing-descriptions
index 53ecbbeb3..7a3518745 100755
--- a/test/integration/test-bug-712435-missing-descriptions
+++ b/test/integration/test-bug-712435-missing-descriptions
@@ -87,13 +87,10 @@ $DESCRIPTION
Description-md5: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
" aptcache show apt-normal
-# displaying the translated Description would be equally valid,
-# but we assume only one description is in a Packages file and
-# so we prefer "Description" over "Description-*" currently.
for variant in 'below' 'middle' 'top'; do
testequal "Package: apt-both-$variant
$PACKAGESTANZA
-$DESCRIPTION
+$TRANSDESCRIPTION
Description-md5: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
" aptcache show apt-both-$variant
done
@@ -122,7 +119,7 @@ X-Some-Flag: yes
testequal "Package: apt-intermixed2
$PACKAGESTANZA
-$DESCRIPTION
+$TRANSDESCRIPTION
Description-md5: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
X-Some-Flag: yes
X-Foo-Flag: Something with a Description
@@ -131,7 +128,7 @@ X-Bar-Flag: no
testequal "Package: apt-intermixed3
$PACKAGESTANZA
-$DESCRIPTION
+$TRANSDESCRIPTION
Description-md5: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
X-Some-Flag: yes
X-Foo-Flag: Something with a Description
diff --git a/test/integration/test-bug-722207-print-uris-even-if-very-quiet b/test/integration/test-bug-722207-print-uris-even-if-very-quiet
index f2d95da19..9a5685703 100755
--- a/test/integration/test-bug-722207-print-uris-even-if-very-quiet
+++ b/test/integration/test-bug-722207-print-uris-even-if-very-quiet
@@ -16,10 +16,10 @@ setupaptarchive
APTARCHIVE=$(readlink -f ./aptarchive)
-testequal "'file://${APTARCHIVE}/pool/main/apt/apt_2_all.deb' apt_2_all.deb 0 MD5Sum:" aptget upgrade -qq --print-uris
-testequal "'file://${APTARCHIVE}/pool/main/apt/apt_2_all.deb' apt_2_all.deb 0 MD5Sum:" aptget dist-upgrade -qq --print-uris
-testequal "'file://${APTARCHIVE}/pool/main/apt/apt_2_all.deb' apt_2_all.deb 0 MD5Sum:" aptget install apt -qq --print-uris
-testequal "'file://${APTARCHIVE}/pool/main/apt/apt_2_all.deb' apt_2_all.deb 0 MD5Sum:" aptget download apt -qq --print-uris
+testequal "'file://${APTARCHIVE}/pool/main/apt/apt_2_all.deb' apt_2_all.deb 0 " aptget upgrade -qq --print-uris
+testequal "'file://${APTARCHIVE}/pool/main/apt/apt_2_all.deb' apt_2_all.deb 0 " aptget dist-upgrade -qq --print-uris
+testequal "'file://${APTARCHIVE}/pool/main/apt/apt_2_all.deb' apt_2_all.deb 0 " aptget install apt -qq --print-uris
+testequal "'file://${APTARCHIVE}/pool/main/apt/apt_2_all.deb' apt_2_all.deb 0 " aptget download apt -qq --print-uris
testequal "'file://${APTARCHIVE}/apt_2.dsc' apt_2.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e
'file://${APTARCHIVE}/apt_2.tar.gz' apt_2.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e" aptget source apt -qq --print-uris
testequal "'http://packages.debian.org/changelogs/pool/main/apt/apt_2/changelog'" aptget changelog apt -qq --print-uris
diff --git a/test/integration/test-bug-745036-new-foreign-invalidates-cache b/test/integration/test-bug-745036-new-foreign-invalidates-cache
new file mode 100755
index 000000000..490cbecdd
--- /dev/null
+++ b/test/integration/test-bug-745036-new-foreign-invalidates-cache
@@ -0,0 +1,29 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture 'amd64'
+
+insertpackage 'unstable' 'cool-foo' 'amd64' '1.0' 'Depends: foo'
+insertpackage 'unstable' 'foo' 'amd64' '1.0' 'Multi-Arch: foreign'
+insertinstalledpackage 'cool-foo' 'amd64' '1.0' 'Depends: foo'
+insertinstalledpackage 'foo' 'amd64' '1.0' 'Multi-Arch: foreign'
+
+setupaptarchive
+
+testsuccess aptget check -s
+
+configarchitecture 'amd64' 'i386'
+testequal 'E: The package cache was built for different architectures: amd64 vs amd64,i386' aptget check -s -o pkgCacheFile::Generate=false
+
+testsuccess aptget check -s
+
+insertinstalledpackage 'awesome-foo' 'i386' '1.0' 'Depends: foo'
+
+testsuccess aptget check -s
+
+testsuccess aptget update --no-download
+
+testsuccess aptget check -s
diff --git a/test/integration/test-bug-747261-arch-specific-conflicts b/test/integration/test-bug-747261-arch-specific-conflicts
new file mode 100755
index 000000000..be971b89e
--- /dev/null
+++ b/test/integration/test-bug-747261-arch-specific-conflicts
@@ -0,0 +1,51 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture 'amd64' 'sparc' 'armel'
+
+msgtest 'Check that dpkg supports' 'arch-specific dependencies'
+set +e
+# this fails always, the question is just how it fails
+dpkg-checkbuilddeps -d 'foobar:barfoo' /dev/null 2>/dev/null >/dev/null
+RETURNCODE=$?
+set -e
+if [ "$RETURNCODE" != '1' ]; then
+ dpkg-checkbuilddeps -d 'foobar:barfoo' /dev/null || true
+ echo "Command had returncode: $RETURNCODE"
+ msgskip
+ exit 0
+else
+ msgpass
+fi
+
+buildsimplenativepackage 'libc6' 'amd64,sparc,armel' '1' 'stable' 'Multi-Arch: same'
+buildsimplenativepackage 'libc6-i386' 'amd64' '1' 'stable' 'Conflicts: libc6:sparc'
+
+setupaptarchive
+
+testsuccess aptget install 'libc6:amd64' 'libc6:sparc' -y
+testdpkginstalled 'libc6:amd64' 'libc6:sparc'
+testdpkgnotinstalled 'libc6-i386' 'libc6:armel'
+
+testsuccess aptget install libc6-i386 -y
+testdpkginstalled 'libc6:amd64' 'libc6-i386'
+testdpkgnotinstalled 'libc6:sparc' 'libc6:armel'
+
+testsuccess aptget install libc6:armel -y
+testdpkginstalled 'libc6:amd64' 'libc6:armel' 'libc6-i386'
+testdpkgnotinstalled 'libc6:sparc'
+
+testsuccess aptget install libc6:sparc -y
+testdpkginstalled 'libc6:amd64' 'libc6:armel' 'libc6:sparc'
+testdpkgnotinstalled 'libc6-i386'
+
+testsuccess aptget purge 'libc6:*' 'libc6-i386' -y
+testdpkgnotinstalled 'libc6:amd64' 'libc6:armel' 'libc6:sparc' 'libc6-i386'
+
+# check that (the actually simpler) single arch is fine, too
+configarchitecture 'amd64'
+testfailure aptget install libc6:sparc -s
+testsuccess aptget install libc6 libc6-i386 -y
diff --git a/test/integration/test-debsrc-hashes b/test/integration/test-debsrc-hashes
deleted file mode 100755
index 5e917232b..000000000
--- a/test/integration/test-debsrc-hashes
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/bin/sh
-set -e
-
-TESTDIR=$(readlink -f $(dirname $0))
-. $TESTDIR/framework
-
-setupenvironment
-configarchitecture "i386"
-
-# pkg-sha256-bad has a bad SHA sum, but good MD5 sum. If apt is
-# checking the best available hash (as it should), this will trigger
-# a hash mismatch.
-
-cat > aptarchive/Sources <<EOF
-Package: pkg-md5-ok
-Binary: pkg-md5-ok
-Version: 1.0
-Maintainer: Joe Sixpack <joe@example.org>
-Architecture: i386
-Files:
- d41d8cd98f00b204e9800998ecf8427e 0 pkg-md5-ok_1.0.dsc
- d41d8cd98f00b204e9800998ecf8427e 0 pkg-md5-ok_1.0.tar.gz
-
-Package: pkg-sha256-ok
-Binary: pkg-sha256-ok
-Version: 1.0
-Maintainer: Joe Sixpack <joe@example.org>
-Architecture: i386
-Files:
- d41d8cd98f00b204e9800998ecf8427e 0 pkg-sha256-ok_1.0.dsc
- d41d8cd98f00b204e9800998ecf8427e 0 pkg-sha256-ok_1.0.tar.gz
-Checksums-Sha1:
- da39a3ee5e6b4b0d3255bfef95601890afd80709 0 pkg-sha256-ok_1.0.dsc
- da39a3ee5e6b4b0d3255bfef95601890afd80709 0 pkg-sha256-ok_1.0.tar.gz
-Checksums-Sha256:
- e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 pkg-sha256-ok_1.0.dsc
- e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 pkg-sha256-ok_1.0.tar.gz
-
-Package: pkg-sha256-bad
-Binary: pkg-sha256-bad
-Version: 1.0
-Maintainer: Joe Sixpack <joe@example.org>
-Architecture: i386
-Files:
- d41d8cd98f00b204e9800998ecf8427e 0 pkg-sha256-bad_1.0.dsc
- d41d8cd98f00b204e9800998ecf8427e 0 pkg-sha256-bad_1.0.tar.gz
-Checksums-Sha1:
- da39a3ee5e6b4b0d3255bfef95601890afd80709 0 pkg-sha256-bad_1.0.dsc
- da39a3ee5e6b4b0d3255bfef95601890afd80709 0 pkg-sha256-bad_1.0.tar.gz
-Checksums-Sha256:
- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 0 pkg-sha256-bad_1.0.dsc
- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 0 pkg-sha256-bad_1.0.tar.gz
-EOF
-
-# create fetchable files
-for x in "pkg-md5-ok" "pkg-sha256-ok" "pkg-sha256-bad"; do
- touch aptarchive/${x}_1.0.dsc
- touch aptarchive/${x}_1.0.tar.gz
-done
-
-testok() {
- msgtest "Test for hash ok of" "$*"
- $* 2>&1 | grep "Download complete" > /dev/null && msgpass || msgfail
-}
-
-testmismatch() {
- msgtest "Test for hash mismatch of" "$*"
- $* 2>&1 | grep "Hash Sum mismatch" > /dev/null && msgpass || msgfail
-}
-
-setupaptarchive
-changetowebserver
-aptget update -qq
-
-testok aptget source -d pkg-md5-ok
-testok aptget source -d pkg-sha256-ok
-testmismatch aptget source -d pkg-sha256-bad
diff --git a/test/integration/test-http-pipeline-messup b/test/integration/test-http-pipeline-messup
new file mode 100755
index 000000000..9c59e1825
--- /dev/null
+++ b/test/integration/test-http-pipeline-messup
@@ -0,0 +1,43 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+
+setupenvironment
+configarchitecture "i386"
+
+buildsimplenativepackage 'pkga' 'all' '1.0' 'stable'
+buildsimplenativepackage 'pkgb' 'all' '1.0' 'stable'
+buildsimplenativepackage 'pkgc' 'all' '1.0' 'stable'
+buildsimplenativepackage 'pkgd' 'all' '1.0' 'stable'
+
+setupaptarchive --no-update
+
+# simulate (and be a predictable) pipeline mess-up by the server/proxy
+changetowebserver \
+ -o 'aptwebserver::overwrite::.*pkga.*::filename=/pool/pkgd_1.0_all.deb' \
+ -o 'aptwebserver::overwrite::.*pkgc.*::filename=/pool/pkgb_1.0_all.deb' \
+ -o 'aptwebserver::overwrite::.*pkgb.*::filename=/pool/pkgc_1.0_all.deb' \
+ -o 'aptwebserver::overwrite::.*pkgd.*::filename=/pool/pkga_1.0_all.deb'
+
+testsuccess aptget update -o Debug::Acquire::http=1 -o Debug::pkgAcquire::Worker=1
+
+# messup is bigger than pipeline: checks if fixup isn't trying to hard
+testfailure aptget download pkga pkgb pkgc pkgd "$@" -o Acquire::http::Pipeline-Depth=2
+testfailure test -f pkga_1.0_all.deb
+
+# ensure that pipeling is enabled for rest of this test
+echo 'Acquire::http::Pipeline-Depth 10;' > rootdir/etc/apt/apt.conf.d/99enable-pipeline
+
+# the output is a bit strange: it looks like it has downloaded pkga 4 times
+testsuccess aptget download pkga pkgb pkgc pkgd -o Debug::Acquire::http=1 -o Debug::pkgAcquire::Worker=1
+for pkg in 'pkga' 'pkgb' 'pkgc' 'pkgd'; do
+ testsuccess test -f ${pkg}_1.0_all.deb
+ testsuccess cmp incoming/${pkg}_1.0_all.deb ${pkg}_1.0_all.deb
+ rm -f ${pkg}_1.0_all.deb
+done
+
+# while hashes will pass (as none are available), sizes will not match, so failure
+# checks that no hashes means that pipeline depth is ignored as we can't fixup
+testfailure aptget download pkga pkgb pkgc pkgd "$@" --allow-unauthenticated -o Acquire::ForceHash=ROT26
diff --git a/test/integration/test-kernel-helper-autoremove b/test/integration/test-kernel-helper-autoremove
index c51caa758..22c36890b 100755
--- a/test/integration/test-kernel-helper-autoremove
+++ b/test/integration/test-kernel-helper-autoremove
@@ -9,7 +9,7 @@ configarchitecture 'amd64'
# the executed script would use the installed apt-config,
# which is outside of our control
msgtest 'Check that the installed apt-config supports' '--no-empty'
-if apt-config dump --no-empty >/dev/null 2>&1; then
+if /usr/bin/apt-config dump --no-empty >/dev/null 2>&1; then
msgpass
else
msgskip
diff --git a/test/integration/test-pdiff-usage b/test/integration/test-pdiff-usage
index afe1ad443..74749d6ab 100755
--- a/test/integration/test-pdiff-usage
+++ b/test/integration/test-pdiff-usage
@@ -13,12 +13,6 @@ changetowebserver
PKGFILE="${TESTDIR}/$(echo "$(basename $0)" | sed 's#^test-#Packages-#')"
-echo '#!/bin/sh
-touch merge-was-used
-/usr/bin/diffindex-rred "$@"' > extrred
-chmod +x extrred
-echo 'Dir::Bin::rred "./extrred";' > rootdir/etc/apt/apt.conf.d/99rred
-
wasmergeused() {
msgtest 'Test for successful execution of' "$*"
local OUTPUT=$(mktemp)
diff --git a/test/integration/test-ubuntu-bug-1098738-apt-get-source-md5sum b/test/integration/test-ubuntu-bug-1098738-apt-get-source-md5sum
new file mode 100755
index 000000000..8c9c9c767
--- /dev/null
+++ b/test/integration/test-ubuntu-bug-1098738-apt-get-source-md5sum
@@ -0,0 +1,262 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+
+setupenvironment
+configarchitecture 'native'
+
+cat > aptarchive/Sources <<EOF
+Package: pkg-md5-ok
+Binary: pkg-md5-ok
+Version: 1.0
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Files:
+ 9604ba9427a280db542279d9ed78400b 3 pkg-md5-ok_1.0.dsc
+ db5570bf61464b46e2bde31ed61a7dc6 3 pkg-md5-ok_1.0.tar.gz
+
+Package: pkg-sha256-ok
+Binary: pkg-sha256-ok
+Version: 1.0
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Files:
+ 9604ba9427a280db542279d9ed78400b 3 pkg-sha256-ok_1.0.dsc
+ db5570bf61464b46e2bde31ed61a7dc6 3 pkg-sha256-ok_1.0.tar.gz
+Checksums-Sha1:
+ 324f464e6151a92cf57b26ef95dcfcf2059a8c44 3 pkg-sha256-ok_1.0.dsc
+ 680254bad1d7ca0d65ec46aaa315d363abf6a50a 3 pkg-sha256-ok_1.0.tar.gz
+Checksums-Sha256:
+ 943d3bf22ac661fb0f59bc4ff68cc12b04ff17a838dfcc2537008eb9c7f3770a 3 pkg-sha256-ok_1.0.dsc
+ 90aebae315675cbf04612de4f7d5874850f48e0b8dd82becbeaa47ca93f5ebfb 3 pkg-sha256-ok_1.0.tar.gz
+
+Package: pkg-sha256-bad
+Binary: pkg-sha256-bad
+Version: 1.0
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Files:
+ 9604ba9427a280db542279d9ed78400b 3 pkg-sha256-bad_1.0.dsc
+ db5570bf61464b46e2bde31ed61a7dc6 3 pkg-sha256-bad_1.0.tar.gz
+Checksums-Sha1:
+ 324f464e6151a92cf57b26ef95dcfcf2059a8c44 3 pkg-sha256-bad_1.0.dsc
+ 680254bad1d7ca0d65ec46aaa315d363abf6a50a 3 pkg-sha256-bad_1.0.tar.gz
+Checksums-Sha256:
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 3 pkg-sha256-bad_1.0.dsc
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 3 pkg-sha256-bad_1.0.tar.gz
+
+Package: pkg-no-md5
+Binary: pkg-no-md5
+Version: 1.0
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Checksums-Sha1:
+ 324f464e6151a92cf57b26ef95dcfcf2059a8c44 3 pkg-no-md5_1.0.dsc
+ 680254bad1d7ca0d65ec46aaa315d363abf6a50a 3 pkg-no-md5_1.0.tar.gz
+Checksums-Sha256:
+ 943d3bf22ac661fb0f59bc4ff68cc12b04ff17a838dfcc2537008eb9c7f3770a 3 pkg-no-md5_1.0.dsc
+ 90aebae315675cbf04612de4f7d5874850f48e0b8dd82becbeaa47ca93f5ebfb 3 pkg-no-md5_1.0.tar.gz
+
+Package: pkg-mixed-ok
+Binary: pkg-mixed-ok
+Version: 1.0
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Checksums-Sha1:
+ 680254bad1d7ca0d65ec46aaa315d363abf6a50a 3 pkg-mixed-ok_1.0.tar.gz
+Checksums-Sha256:
+ 943d3bf22ac661fb0f59bc4ff68cc12b04ff17a838dfcc2537008eb9c7f3770a 3 pkg-mixed-ok_1.0.dsc
+
+Package: pkg-mixed-sha1-bad
+Binary: pkg-mixed-sha1-bad
+Version: 1.0
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Checksums-Sha1:
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 3 pkg-mixed-sha1-bad_1.0.dsc
+Checksums-Sha256:
+ 90aebae315675cbf04612de4f7d5874850f48e0b8dd82becbeaa47ca93f5ebfb 3 pkg-mixed-sha1-bad_1.0.tar.gz
+
+Package: pkg-mixed-sha2-bad
+Binary: pkg-mixed-sha2-bad
+Version: 1.0
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Checksums-Sha1:
+ 324f464e6151a92cf57b26ef95dcfcf2059a8c44 3 pkg-mixed-sha2-bad_1.0.dsc
+Checksums-Sha256:
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 3 pkg-mixed-sha2-bad_1.0.tar.gz
+
+Package: pkg-md5-disagree
+Binary: pkg-md5-disagree
+Version: 1.0
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Files:
+ 9604ba9427a280db542279d9ed78400b 3 pkg-md5-disagree_1.0.dsc
+ db5570bf61464b46e2bde31ed61a7dc6 3 pkg-md5-disagree_1.0.tar.gz
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 3 pkg-md5-disagree_1.0.dsc
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 3 pkg-md5-disagree_1.0.tar.gz
+
+Package: pkg-md5-agree
+Binary: pkg-md5-agree
+Version: 1.0
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Files:
+ 9604ba9427a280db542279d9ed78400b 3 pkg-md5-agree_1.0.dsc
+ db5570bf61464b46e2bde31ed61a7dc6 3 pkg-md5-agree_1.0.tar.gz
+ db5570bf61464b46e2bde31ed61a7dc6 3 pkg-md5-agree_1.0.tar.gz
+ 9604ba9427a280db542279d9ed78400b 3 pkg-md5-agree_1.0.dsc
+
+Package: pkg-sha256-disagree
+Binary: pkg-sha256-disagree
+Version: 1.0
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Files:
+ 9604ba9427a280db542279d9ed78400b 3 pkg-sha256-disagree_1.0.dsc
+ db5570bf61464b46e2bde31ed61a7dc6 3 pkg-sha256-disagree_1.0.tar.gz
+Checksums-Sha1:
+ 324f464e6151a92cf57b26ef95dcfcf2059a8c44 3 pkg-sha256-disagree_1.0.dsc
+ 680254bad1d7ca0d65ec46aaa315d363abf6a50a 3 pkg-sha256-disagree_1.0.tar.gz
+Checksums-Sha256:
+ 943d3bf22ac661fb0f59bc4ff68cc12b04ff17a838dfcc2537008eb9c7f3770a 3 pkg-sha256-disagree_1.0.dsc
+ 90aebae315675cbf04612de4f7d5874850f48e0b8dd82becbeaa47ca93f5ebfb 3 pkg-sha256-disagree_1.0.tar.gz
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 3 pkg-sha256-disagree_1.0.dsc
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 3 pkg-sha256-disagree_1.0.tar.gz
+EOF
+
+# create fetchable files
+for x in 'pkg-md5-ok' 'pkg-sha256-ok' 'pkg-sha256-bad' 'pkg-no-md5' \
+ 'pkg-mixed-ok' 'pkg-mixed-sha1-bad' 'pkg-mixed-sha2-bad' \
+ 'pkg-md5-agree' 'pkg-md5-disagree' 'pkg-sha256-disagree'; do
+ echo -n 'dsc' > aptarchive/${x}_1.0.dsc
+ echo -n 'tar' > aptarchive/${x}_1.0.tar.gz
+done
+
+setupaptarchive
+changetowebserver
+testsuccess aptget update
+
+testok() {
+ rm -f ${1}_1.0.dsc ${1}_1.0.tar.gz
+ testequal "Reading package lists...
+Building dependency tree...
+Need to get 6 B of source archives.
+Get:1 http://localhost:8080/ $1 1.0 (dsc) [3 B]
+Get:2 http://localhost:8080/ $1 1.0 (tar) [3 B]
+Download complete and in download only mode" aptget source -d "$@"
+ msgtest 'Files were successfully downloaded for' "$1"
+ testsuccess --nomsg test -e ${1}_1.0.dsc -a -e ${1}_1.0.tar.gz
+ rm -f ${1}_1.0.dsc ${1}_1.0.tar.gz
+}
+
+testkeep() {
+ echo -n 'dsc' > ${1}_1.0.dsc
+ echo -n 'tar' > ${1}_1.0.tar.gz
+ testequal "Reading package lists...
+Building dependency tree...
+Skipping already downloaded file '${1}_1.0.dsc'
+Skipping already downloaded file '${1}_1.0.tar.gz'
+Need to get 0 B of source archives.
+Download complete and in download only mode" aptget source -d "$@"
+ msgtest 'Files already downloaded are kept for' "$1"
+ testsuccess --nomsg test -e ${1}_1.0.dsc -a -e ${1}_1.0.tar.gz
+ rm -f ${1}_1.0.dsc ${1}_1.0.tar.gz
+}
+
+testmismatch() {
+ rm -f ${1}_1.0.dsc ${1}_1.0.tar.gz
+ testequal "Reading package lists...
+Building dependency tree...
+Need to get 6 B of source archives.
+Get:1 http://localhost:8080/ $1 1.0 (dsc) [3 B]
+Get:2 http://localhost:8080/ $1 1.0 (tar) [3 B]
+E: Failed to fetch http://localhost:8080/${1}_1.0.dsc Hash Sum mismatch
+
+E: Failed to fetch http://localhost:8080/${1}_1.0.tar.gz Hash Sum mismatch
+
+E: Failed to fetch some archives." aptget source -d "$@"
+ msgtest 'Files were not download as they have hashsum mismatches for' "$1"
+ testfailure --nomsg test -e ${1}_1.0.dsc -a -e ${1}_1.0.tar.gz
+
+ rm -f ${1}_1.0.dsc ${1}_1.0.tar.gz
+ testequal "Reading package lists...
+Building dependency tree...
+Skipping download of file 'pkg-sha256-bad_1.0.dsc' as requested hashsum is not available for authentication
+Skipping download of file 'pkg-sha256-bad_1.0.tar.gz' as requested hashsum is not available for authentication
+Need to get 0 B of source archives.
+Download complete and in download only mode" aptget source -d "$@" -o Acquire::ForceHash=ROT26
+ msgtest 'Files were not download as hash is unavailable for' "$1"
+ testfailure --nomsg test -e ${1}_1.0.dsc -a -e ${1}_1.0.tar.gz
+
+ rm -f ${1}_1.0.dsc ${1}_1.0.tar.gz
+ testequal "Reading package lists...
+Building dependency tree...
+Need to get 6 B of source archives.
+Get:1 http://localhost:8080/ $1 1.0 (dsc) [3 B]
+Get:2 http://localhost:8080/ $1 1.0 (tar) [3 B]
+Download complete and in download only mode" aptget source --allow-unauthenticated -d "$@" -o Acquire::ForceHash=ROT26
+ msgtest 'Files were downloaded unauthenticated as user allowed it' "$1"
+ testsuccess --nomsg test -e ${1}_1.0.dsc -a -e ${1}_1.0.tar.gz
+}
+
+testok pkg-md5-ok
+testkeep pkg-md5-ok
+testok pkg-sha256-ok
+testkeep pkg-sha256-ok
+
+# pkg-sha256-bad has a bad SHA sum, but good MD5 sum. If apt is
+# checking the best available hash (as it should), this will trigger
+# a hash mismatch.
+testmismatch pkg-sha256-bad
+testmismatch pkg-sha256-bad
+testok pkg-sha256-bad -o Acquire::ForceHash=MD5Sum
+
+# not having MD5 sum doesn't mean the file doesn't exist at all …
+testok pkg-no-md5
+testok pkg-no-md5 -o Acquire::ForceHash=SHA256
+testequal "Reading package lists...
+Building dependency tree...
+Skipping download of file 'pkg-no-md5_1.0.dsc' as requested hashsum is not available for authentication
+Skipping download of file 'pkg-no-md5_1.0.tar.gz' as requested hashsum is not available for authentication
+Need to get 0 B of source archives.
+Download complete and in download only mode" aptget source -d pkg-no-md5 -o Acquire::ForceHash=MD5Sum
+msgtest 'Files were not download as MD5 is not available for this package' 'pkg-no-md5'
+testfailure --nomsg test -e pkg-no-md5_1.0.dsc -a -e pkg-no-md5_1.0.tar.gz
+
+# deal with cases in which we haven't for all files the same checksum type
+# mostly pathologic as this shouldn't happen, but just to be sure
+testok pkg-mixed-ok
+testequal 'Reading package lists...
+Building dependency tree...
+Need to get 6 B of source archives.
+Get:1 http://localhost:8080/ pkg-mixed-sha1-bad 1.0 (tar) [3 B]
+Get:2 http://localhost:8080/ pkg-mixed-sha1-bad 1.0 (dsc) [3 B]
+E: Failed to fetch http://localhost:8080/pkg-mixed-sha1-bad_1.0.dsc Hash Sum mismatch
+
+E: Failed to fetch some archives.' aptget source -d pkg-mixed-sha1-bad
+msgtest 'Only tar file is downloaded as the dsc has hashsum mismatch' 'pkg-mixed-sha1-bad'
+testsuccess --nomsg test ! -e pkg-mixed-sha1-bad_1.0.dsc -a -e pkg-mixed-sha1-bad_1.0.tar.gz
+testequal 'Reading package lists...
+Building dependency tree...
+Need to get 6 B of source archives.
+Get:1 http://localhost:8080/ pkg-mixed-sha2-bad 1.0 (tar) [3 B]
+Get:2 http://localhost:8080/ pkg-mixed-sha2-bad 1.0 (dsc) [3 B]
+E: Failed to fetch http://localhost:8080/pkg-mixed-sha2-bad_1.0.tar.gz Hash Sum mismatch
+
+E: Failed to fetch some archives.' aptget source -d pkg-mixed-sha2-bad
+msgtest 'Only dsc file is downloaded as the tar has hashsum mismatch' 'pkg-mixed-sha2-bad'
+testsuccess --nomsg test -e pkg-mixed-sha2-bad_1.0.dsc -a ! -e pkg-mixed-sha2-bad_1.0.tar.gz
+
+# it gets even more pathologic: multiple entries for one file, some even disagreeing!
+testok pkg-md5-agree
+testequal 'Reading package lists...
+Building dependency tree...
+E: Error parsing checksum in Files of source package pkg-md5-disagree' aptget source -d pkg-md5-disagree
+testequal 'Reading package lists...
+Building dependency tree...
+E: Error parsing checksum in Checksums-SHA256 of source package pkg-sha256-disagree' aptget source -d pkg-sha256-disagree
diff --git a/test/integration/test-ubuntu-bug-346386-apt-get-update-paywall b/test/integration/test-ubuntu-bug-346386-apt-get-update-paywall
index 1a7db0adc..8e50843f3 100755
--- a/test/integration/test-ubuntu-bug-346386-apt-get-update-paywall
+++ b/test/integration/test-ubuntu-bug-346386-apt-get-update-paywall
@@ -22,7 +22,7 @@ Config-Item: Acquire::http::DependOnSTDIN=0
600 Acquire URI
URI: http://localhost:8080/holygrail
Filename: knights-talking
-' | LD_LIBRARY_PATH=${BUILDDIRECTORY} ${METHODSDIR}/http >/dev/null 2>&1 && msgpass || msgfail
+' | runapt ${METHODSDIR}/http >/dev/null 2>&1 && msgpass || msgfail
testfileequal knights-talking 'ni ni ni'
ensure_n_canary_strings_in_dir() {
diff --git a/test/libapt/hashsums_test.cc b/test/libapt/hashsums_test.cc
index c06d85e03..2159996ff 100644
--- a/test/libapt/hashsums_test.cc
+++ b/test/libapt/hashsums_test.cc
@@ -1,5 +1,6 @@
#include <config.h>
+#include <apt-pkg/configuration.h>
#include <apt-pkg/md5.h>
#include <apt-pkg/sha1.h>
#include <apt-pkg/sha2.h>
@@ -166,20 +167,26 @@ TEST(HashSumsTest, FileBased)
{
Hashes hashes;
hashes.AddFD(fd.Fd());
- EXPECT_EQ(md5.Value(), hashes.MD5.Result().Value());
- EXPECT_EQ(sha1.Value(), hashes.SHA1.Result().Value());
- EXPECT_EQ(sha256.Value(), hashes.SHA256.Result().Value());
- EXPECT_EQ(sha512.Value(), hashes.SHA512.Result().Value());
+ HashStringList list = hashes.GetHashStringList();
+ EXPECT_FALSE(list.empty());
+ EXPECT_EQ(4, list.size());
+ EXPECT_EQ(md5.Value(), list.find("MD5Sum")->HashValue());
+ EXPECT_EQ(sha1.Value(), list.find("SHA1")->HashValue());
+ EXPECT_EQ(sha256.Value(), list.find("SHA256")->HashValue());
+ EXPECT_EQ(sha512.Value(), list.find("SHA512")->HashValue());
}
unsigned long sz = fd.FileSize();
fd.Seek(0);
{
Hashes hashes;
hashes.AddFD(fd.Fd(), sz);
- EXPECT_EQ(md5.Value(), hashes.MD5.Result().Value());
- EXPECT_EQ(sha1.Value(), hashes.SHA1.Result().Value());
- EXPECT_EQ(sha256.Value(), hashes.SHA256.Result().Value());
- EXPECT_EQ(sha512.Value(), hashes.SHA512.Result().Value());
+ HashStringList list = hashes.GetHashStringList();
+ EXPECT_FALSE(list.empty());
+ EXPECT_EQ(4, list.size());
+ EXPECT_EQ(md5.Value(), list.find("MD5Sum")->HashValue());
+ EXPECT_EQ(sha1.Value(), list.find("SHA1")->HashValue());
+ EXPECT_EQ(sha256.Value(), list.find("SHA256")->HashValue());
+ EXPECT_EQ(sha512.Value(), list.find("SHA512")->HashValue());
}
fd.Seek(0);
{
@@ -207,16 +214,118 @@ TEST(HashSumsTest, FileBased)
}
fd.Close();
- {
- HashString sha2("SHA256", sha256.Value());
- EXPECT_TRUE(sha2.VerifyFile(__FILE__));
- }
- {
- HashString sha2("SHA512", sha512.Value());
- EXPECT_TRUE(sha2.VerifyFile(__FILE__));
- }
- {
- HashString sha2("SHA256:" + sha256.Value());
- EXPECT_TRUE(sha2.VerifyFile(__FILE__));
- }
+ HashString sha2file("SHA512", sha512.Value());
+ EXPECT_TRUE(sha2file.VerifyFile(__FILE__));
+ HashString sha2wrong("SHA512", "00000000000");
+ EXPECT_FALSE(sha2wrong.VerifyFile(__FILE__));
+ EXPECT_EQ(sha2file, sha2file);
+ EXPECT_TRUE(sha2file == sha2file);
+ EXPECT_NE(sha2file, sha2wrong);
+ EXPECT_TRUE(sha2file != sha2wrong);
+
+ HashString sha2big("SHA256", sha256.Value());
+ EXPECT_TRUE(sha2big.VerifyFile(__FILE__));
+ HashString sha2small("sha256:" + sha256.Value());
+ EXPECT_TRUE(sha2small.VerifyFile(__FILE__));
+ EXPECT_EQ(sha2big, sha2small);
+ EXPECT_TRUE(sha2big == sha2small);
+ EXPECT_FALSE(sha2big != sha2small);
+
+ HashStringList hashes;
+ EXPECT_TRUE(hashes.empty());
+ EXPECT_TRUE(hashes.push_back(sha2file));
+ EXPECT_FALSE(hashes.empty());
+ EXPECT_EQ(1, hashes.size());
+
+ HashStringList wrong;
+ EXPECT_TRUE(wrong.push_back(sha2wrong));
+ EXPECT_NE(wrong, hashes);
+ EXPECT_FALSE(wrong == hashes);
+ EXPECT_TRUE(wrong != hashes);
+
+ HashStringList similar;
+ EXPECT_TRUE(similar.push_back(sha2big));
+ EXPECT_NE(similar, hashes);
+ EXPECT_FALSE(similar == hashes);
+ EXPECT_TRUE(similar != hashes);
+
+ EXPECT_TRUE(hashes.push_back(sha2big));
+ EXPECT_EQ(2, hashes.size());
+ EXPECT_TRUE(hashes.push_back(sha2small));
+ EXPECT_EQ(2, hashes.size());
+ EXPECT_FALSE(hashes.push_back(sha2wrong));
+ EXPECT_EQ(2, hashes.size());
+ EXPECT_TRUE(hashes.VerifyFile(__FILE__));
+
+ EXPECT_EQ(similar, hashes);
+ EXPECT_TRUE(similar == hashes);
+ EXPECT_FALSE(similar != hashes);
+ similar.clear();
+ EXPECT_TRUE(similar.empty());
+ EXPECT_EQ(0, similar.size());
+ EXPECT_NE(similar, hashes);
+ EXPECT_FALSE(similar == hashes);
+ EXPECT_TRUE(similar != hashes);
+}
+TEST(HashSumsTest, HashStringList)
+{
+ _config->Clear("Acquire::ForceHash");
+
+ HashStringList list;
+ EXPECT_TRUE(list.empty());
+ EXPECT_FALSE(list.usable());
+ EXPECT_EQ(0, list.size());
+ EXPECT_EQ(NULL, list.find(NULL));
+ EXPECT_EQ(NULL, list.find(""));
+ EXPECT_EQ(NULL, list.find("MD5Sum"));
+
+ HashStringList list2;
+ EXPECT_FALSE(list == list2);
+ EXPECT_TRUE(list != list2);
+
+ Hashes hashes;
+ hashes.Add("The quick brown fox jumps over the lazy dog");
+ list = hashes.GetHashStringList();
+ EXPECT_FALSE(list.empty());
+ EXPECT_TRUE(list.usable());
+ EXPECT_EQ(4, list.size());
+ EXPECT_TRUE(NULL != list.find(NULL));
+ EXPECT_TRUE(NULL != list.find(""));
+ EXPECT_TRUE(NULL != list.find("MD5Sum"));
+ EXPECT_TRUE(NULL == list.find("ROT26"));
+
+ _config->Set("Acquire::ForceHash", "MD5Sum");
+ EXPECT_FALSE(list.empty());
+ EXPECT_TRUE(list.usable());
+ EXPECT_EQ(4, list.size());
+ EXPECT_TRUE(NULL != list.find(NULL));
+ EXPECT_TRUE(NULL != list.find(""));
+ EXPECT_TRUE(NULL != list.find("MD5Sum"));
+ EXPECT_TRUE(NULL == list.find("ROT26"));
+
+ _config->Set("Acquire::ForceHash", "ROT26");
+ EXPECT_FALSE(list.empty());
+ EXPECT_FALSE(list.usable());
+ EXPECT_EQ(4, list.size());
+ EXPECT_TRUE(NULL == list.find(NULL));
+ EXPECT_TRUE(NULL == list.find(""));
+ EXPECT_TRUE(NULL != list.find("MD5Sum"));
+ EXPECT_TRUE(NULL == list.find("ROT26"));
+
+ _config->Clear("Acquire::ForceHash");
+
+ list2.push_back(*list.find("MD5Sum"));
+ EXPECT_TRUE(list == list2);
+ EXPECT_FALSE(list != list2);
+
+ // introduce a mismatch to the list
+ list2.push_back(HashString("SHA1", "cacecbd74968bc90ea3342767e6b94f46ddbcafc"));
+ EXPECT_FALSE(list == list2);
+ EXPECT_TRUE(list != list2);
+
+ _config->Set("Acquire::ForceHash", "MD5Sum");
+ EXPECT_TRUE(list == list2);
+ EXPECT_FALSE(list != list2);
+
+ _config->Clear("Acquire::ForceHash");
}
diff --git a/test/libapt/tagfile_test.cc b/test/libapt/tagfile_test.cc
index 1bac75b55..df618ea16 100644
--- a/test/libapt/tagfile_test.cc
+++ b/test/libapt/tagfile_test.cc
@@ -7,6 +7,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <sstream>
#include <gtest/gtest.h>
@@ -34,3 +35,181 @@ TEST(TagFileTest,SingleField)
// There is only one section in this tag file
EXPECT_FALSE(tfile.Step(section));
}
+
+TEST(TagFileTest,MultipleSections)
+{
+ FileFd fd;
+ createTemporaryFile("bigsection", fd, NULL, "Package: pkgA\n"
+ "Version: 1\n"
+ "Size: 100\n"
+ "Description: aaa\n"
+ " aaa\n"
+ "\n"
+ "Package: pkgB\n"
+ "Version: 1\n"
+ "Flag: no\n"
+ "Description: bbb\n"
+ "\n"
+ "Package: pkgC\n"
+ "Version: 2\n"
+ "Flag: yes\n"
+ "Description:\n"
+ " ccc\n"
+ );
+
+ pkgTagFile tfile(&fd);
+ pkgTagSection section;
+ EXPECT_FALSE(section.Exists("Version"));
+
+ EXPECT_TRUE(tfile.Step(section));
+ EXPECT_EQ(4, section.Count());
+ EXPECT_TRUE(section.Exists("Version"));
+ EXPECT_TRUE(section.Exists("Package"));
+ EXPECT_TRUE(section.Exists("Size"));
+ EXPECT_FALSE(section.Exists("Flag"));
+ EXPECT_TRUE(section.Exists("Description"));
+ EXPECT_EQ("pkgA", section.FindS("Package"));
+ EXPECT_EQ("1", section.FindS("Version"));
+ EXPECT_EQ(1, section.FindULL("Version"));
+ EXPECT_EQ(100, section.FindULL("Size"));
+ unsigned long Flags = 1;
+ EXPECT_TRUE(section.FindFlag("Flag", Flags, 1));
+ EXPECT_EQ(1, Flags);
+ Flags = 0;
+ EXPECT_TRUE(section.FindFlag("Flag", Flags, 1));
+ EXPECT_EQ(0, Flags);
+ EXPECT_EQ("aaa\n aaa", section.FindS("Description"));
+
+
+ EXPECT_TRUE(tfile.Step(section));
+ EXPECT_EQ(4, section.Count());
+ EXPECT_TRUE(section.Exists("Version"));
+ EXPECT_TRUE(section.Exists("Package"));
+ EXPECT_FALSE(section.Exists("Size"));
+ EXPECT_TRUE(section.Exists("Flag"));
+ EXPECT_TRUE(section.Exists("Description"));
+ EXPECT_EQ("pkgB", section.FindS("Package"));
+ EXPECT_EQ("1", section.FindS("Version"));
+ EXPECT_EQ(1, section.FindULL("Version"));
+ EXPECT_EQ(0, section.FindULL("Size"));
+ Flags = 1;
+ EXPECT_TRUE(section.FindFlag("Flag", Flags, 1));
+ EXPECT_EQ(0, Flags);
+ Flags = 0;
+ EXPECT_TRUE(section.FindFlag("Flag", Flags, 1));
+ EXPECT_EQ(0, Flags);
+ EXPECT_EQ("bbb", section.FindS("Description"));
+
+ EXPECT_TRUE(tfile.Step(section));
+ EXPECT_EQ(4, section.Count());
+ EXPECT_TRUE(section.Exists("Version"));
+ EXPECT_TRUE(section.Exists("Package"));
+ EXPECT_FALSE(section.Exists("Size"));
+ EXPECT_TRUE(section.Exists("Flag"));
+ EXPECT_TRUE(section.Exists("Description"));
+ EXPECT_EQ("pkgC", section.FindS("Package"));
+ EXPECT_EQ("2", section.FindS("Version"));
+ EXPECT_EQ(2, section.FindULL("Version"));
+ Flags = 0;
+ EXPECT_TRUE(section.FindFlag("Flag", Flags, 1));
+ EXPECT_EQ(1, Flags);
+ Flags = 1;
+ EXPECT_TRUE(section.FindFlag("Flag", Flags, 1));
+ EXPECT_EQ(1, Flags);
+ EXPECT_EQ("ccc", section.FindS("Description"));
+
+ // There is no section left in this tag file
+ EXPECT_FALSE(tfile.Step(section));
+}
+
+TEST(TagFileTest,BigSection)
+{
+ size_t const count = 500;
+ std::stringstream content;
+ for (size_t i = 0; i < count; ++i)
+ content << "Field-" << i << ": " << (2000 + i) << std::endl;
+
+ FileFd fd;
+ createTemporaryFile("bigsection", fd, NULL, content.str().c_str());
+
+ pkgTagFile tfile(&fd);
+ pkgTagSection section;
+ EXPECT_TRUE(tfile.Step(section));
+
+ EXPECT_EQ(count, section.Count());
+ for (size_t i = 0; i < count; ++i)
+ {
+ std::stringstream name;
+ name << "Field-" << i;
+ EXPECT_TRUE(section.Exists(name.str().c_str())) << name.str() << " does not exist";
+ EXPECT_EQ((2000 + i), section.FindULL(name.str().c_str()));
+ }
+
+ // There is only one section in this tag file
+ EXPECT_FALSE(tfile.Step(section));
+}
+
+TEST(TagFileTest, PickedUpFromPreviousCall)
+{
+ size_t const count = 500;
+ std::stringstream contentstream;
+ for (size_t i = 0; i < count; ++i)
+ contentstream << "Field-" << i << ": " << (2000 + i) << std::endl;
+ contentstream << std::endl << std::endl;
+ std::string content = contentstream.str();
+
+ pkgTagSection section;
+ EXPECT_FALSE(section.Scan(content.c_str(), content.size()/2));
+ EXPECT_NE(0, section.Count());
+ EXPECT_NE(count, section.Count());
+ EXPECT_TRUE(section.Scan(content.c_str(), content.size(), false));
+ EXPECT_EQ(count, section.Count());
+
+ for (size_t i = 0; i < count; ++i)
+ {
+ std::stringstream name;
+ name << "Field-" << i;
+ EXPECT_TRUE(section.Exists(name.str().c_str())) << name.str() << " does not exist";
+ EXPECT_EQ((2000 + i), section.FindULL(name.str().c_str()));
+ }
+}
+
+TEST(TagFileTest, SpacesEverywhere)
+{
+ std::string content =
+ "Package: pkgA\n"
+ "Package: pkgB\n"
+ "NoSpaces:yes\n"
+ "TagSpaces\t :yes\n"
+ "ValueSpaces: \tyes\n"
+ "BothSpaces \t:\t yes\n"
+ "TrailingSpaces: yes\t \n"
+ "Naming Space: yes\n"
+ "Naming Spaces: yes\n"
+ "Package : pkgC \n"
+ "Multi-Colon::yes:\n"
+ "\n\n";
+
+ pkgTagSection section;
+ EXPECT_TRUE(section.Scan(content.c_str(), content.size()));
+ EXPECT_TRUE(section.Exists("Package"));
+ EXPECT_TRUE(section.Exists("NoSpaces"));
+ EXPECT_TRUE(section.Exists("TagSpaces"));
+ EXPECT_TRUE(section.Exists("ValueSpaces"));
+ EXPECT_TRUE(section.Exists("BothSpaces"));
+ EXPECT_TRUE(section.Exists("TrailingSpaces"));
+ EXPECT_TRUE(section.Exists("Naming Space"));
+ EXPECT_TRUE(section.Exists("Naming Spaces"));
+ EXPECT_TRUE(section.Exists("Multi-Colon"));
+ EXPECT_EQ("pkgC", section.FindS("Package"));
+ EXPECT_EQ("yes", section.FindS("NoSpaces"));
+ EXPECT_EQ("yes", section.FindS("TagSpaces"));
+ EXPECT_EQ("yes", section.FindS("ValueSpaces"));
+ EXPECT_EQ("yes", section.FindS("BothSpaces"));
+ EXPECT_EQ("yes", section.FindS("TrailingSpaces"));
+ EXPECT_EQ("yes", section.FindS("Naming Space"));
+ EXPECT_EQ("yes", section.FindS("Naming Spaces"));
+ EXPECT_EQ(":yes:", section.FindS("Multi-Colon"));
+ // overridden values are still present, but not really accessible
+ EXPECT_EQ(11, section.Count());
+}