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)
+#if __GNUC__ >= 4
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+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;
}
+#if __GNUC__ >= 4
+ #pragma GCC diagnostic pop
+#endif
/*}}}*/
// Acquire::Item::~Item - Destructor /*{{{*/
// ---------------------------------------------------------------------
// 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..
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);
// 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);
// 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)
return;
}
- Item::Done(Message,Size,Md5Hash,Cnf);
+ Item::Done(Message, Size, Hashes, Cnf);
string FinalFile = _config->FindDir("Dir::State::lists")+URItoFileName(Desc.URI);
* the original packages file
*/
pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner,
- string URI,string URIDesc,string ShortDesc,
- HashString ExpectedHash)
- : Item(Owner), RealURI(URI), ExpectedHash(ExpectedHash),
- Description(URIDesc)
+ IndexTarget const * const Target,
+ HashStringList const &ExpectedHashes,
+ indexRecords *MetaIndexParser)
+ : pkgAcqBaseIndex(Owner, Target, ExpectedHashes, MetaIndexParser)
{
Debug = _config->FindB("Debug::pkgAcquire::Diffs",false);
- Desc.Description = URIDesc + "/DiffIndex";
+ RealURI = Target->URI;
Desc.Owner = this;
- Desc.ShortDesc = ShortDesc;
- Desc.URI = URI + ".diff/Index";
+ Desc.Description = Target->Description + "/DiffIndex";
+ Desc.ShortDesc = Target->ShortDesc;
+ Desc.URI = Target->URI + ".diff/Index";
DestFile = _config->FindDir("Dir::State::lists") + "partial/";
DestFile += URItoFileName(Desc.URI);
// 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(Desc.URI);
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, RealURI, Description, Desc.ShortDesc,
- ExpectedHash, ServerSha1, available_patches);
+ new pkgAcqIndexDiffs(Owner, Target, ExpectedHashes, MetaIndexParser,
+ ServerSha1, available_patches);
return true;
}
else
}
if (pdiff_merge == false)
- new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc,
- ExpectedHash, ServerSha1, available_patches);
- else
+ {
+ new pkgAcqIndexDiffs(Owner, Target, ExpectedHashes, MetaIndexParser,
+ ServerSha1, available_patches);
+ }
+ else
{
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, RealURI, Description, Desc.ShortDesc, ExpectedHash,
- available_patches[i], diffs);
+ (*diffs)[i] = new pkgAcqIndexMergeDiffs(Owner, Target,
+ ExpectedHashes,
+ MetaIndexParser,
+ available_patches[i],
+ diffs);
}
Complete = false;
std::clog << "pkgAcqDiffIndex failed: " << Desc.URI << " with " << Message << std::endl
<< "Falling back to normal index file acquire" << std::endl;
- new pkgAcqIndex(Owner, RealURI, Description, Desc.ShortDesc,
- ExpectedHash);
+ 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);
* for each diff and the index
*/
pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire *Owner,
- string URI,string URIDesc,string ShortDesc,
- HashString ExpectedHash,
+ struct IndexTarget const * const Target,
+ HashStringList const &ExpectedHashes,
+ indexRecords *MetaIndexParser,
string ServerSha1,
vector<DiffInfo> diffs)
- : Item(Owner), RealURI(URI), ExpectedHash(ExpectedHash),
+ : pkgAcqBaseIndex(Owner, Target, ExpectedHashes, MetaIndexParser),
available_patches(diffs), ServerSha1(ServerSha1)
{
DestFile = _config->FindDir("Dir::State::lists") + "partial/";
- DestFile += URItoFileName(URI);
+ DestFile += URItoFileName(Target->URI);
Debug = _config->FindB("Debug::pkgAcquire::Diffs",false);
- Description = URIDesc;
+ RealURI = Target->URI;
Desc.Owner = this;
- Desc.ShortDesc = ShortDesc;
+ Description = Target->Description;
+ Desc.ShortDesc = Target->ShortDesc;
if(available_patches.empty() == true)
{
if(Debug)
std::clog << "pkgAcqIndexDiffs failed: " << Desc.URI << " with " << Message << std::endl
<< "Falling back to normal index file acquire" << std::endl;
- new pkgAcqIndex(Owner, RealURI, Description,Desc.ShortDesc,
- ExpectedHash);
+ new pkgAcqIndex(Owner, Target, ExpectedHashes, MetaIndexParser);
Finish();
}
/*}}}*/
DestFile = _config->FindDir("Dir::State::lists");
DestFile += URItoFileName(RealURI);
- if(!ExpectedHash.empty() && !ExpectedHash.VerifyFile(DestFile))
+ if(HashSums().usable() && !HashSums().VerifyFile(DestFile))
{
RenameOnError(HashSumMismatch);
Dequeue();
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);
Local = true;
Desc.URI = "rred:" + FinalFile;
QueueURI(Desc);
+ ActiveSubprocess = "rred";
+#if __GNUC__ >= 4
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
Mode = "rred";
+#if __GNUC__ >= 4
+ #pragma GCC diagnostic pop
+#endif
return;
}
// see if there is more to download
if(available_patches.empty() == false) {
- new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc,
- ExpectedHash, ServerSha1, available_patches);
+ new pkgAcqIndexDiffs(Owner, Target,
+ ExpectedHashes, MetaIndexParser,
+ ServerSha1, available_patches);
return Finish();
} else
return Finish(true);
/*}}}*/
// AcqIndexMergeDiffs::AcqIndexMergeDiffs - Constructor /*{{{*/
pkgAcqIndexMergeDiffs::pkgAcqIndexMergeDiffs(pkgAcquire *Owner,
- string const &URI, string const &URIDesc,
- string const &ShortDesc, HashString const &ExpectedHash,
- DiffInfo const &patch,
- std::vector<pkgAcqIndexMergeDiffs*> const * const allPatches)
- : Item(Owner), RealURI(URI), ExpectedHash(ExpectedHash),
- patch(patch),allPatches(allPatches), State(StateFetchDiff)
+ struct IndexTarget const * const Target,
+ HashStringList const &ExpectedHashes,
+ indexRecords *MetaIndexParser,
+ DiffInfo const &patch,
+ std::vector<pkgAcqIndexMergeDiffs*> const * const allPatches)
+ : pkgAcqBaseIndex(Owner, Target, ExpectedHashes, MetaIndexParser),
+ patch(patch), allPatches(allPatches), State(StateFetchDiff)
{
DestFile = _config->FindDir("Dir::State::lists") + "partial/";
- DestFile += URItoFileName(URI);
+ DestFile += URItoFileName(Target->URI);
Debug = _config->FindB("Debug::pkgAcquire::Diffs",false);
- Description = URIDesc;
+ RealURI = Target->URI;
Desc.Owner = this;
- Desc.ShortDesc = ShortDesc;
+ Description = Target->Description;
+ Desc.ShortDesc = Target->ShortDesc;
Desc.URI = RealURI + ".diff/" + patch.file + ".gz";
Desc.Description = Description + " " + patch.file + string(".pdiff");
// first failure means we should fallback
State = StateErrorDiff;
std::clog << "Falling back to normal index file acquire" << std::endl;
- new pkgAcqIndex(Owner, RealURI, Description,Desc.ShortDesc,
- ExpectedHash);
+ 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);
Local = true;
Desc.URI = "rred:" + FinalFile;
QueueURI(Desc);
+ ActiveSubprocess = "rred";
+#if __GNUC__ >= 4
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
Mode = "rred";
+#if __GNUC__ >= 4
+ #pragma GCC diagnostic pop
+#endif
return;
}
// success in download/apply all diffs, clean up
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;
instantiated to fetch the revision file */
pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner,
string URI,string URIDesc,string ShortDesc,
- HashString ExpectedHash, string comprExt)
- : Item(Owner), RealURI(URI), ExpectedHash(ExpectedHash)
+ HashStringList const &ExpectedHash, string comprExt)
+ : pkgAcqBaseIndex(Owner, NULL, ExpectedHash, NULL), RealURI(URI)
{
if(comprExt.empty() == true)
{
Init(URI, URIDesc, ShortDesc);
}
pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner, IndexTarget const *Target,
- HashString const &ExpectedHash, indexRecords const *MetaIndexParser)
- : Item(Owner), RealURI(Target->URI), ExpectedHash(ExpectedHash)
+ 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)
DestFile += URItoFileName(URI);
std::string const comprExt = CompressionExtension.substr(0, CompressionExtension.find(' '));
+ std::string MetaKey;
if (comprExt == "uncompressed")
+ {
Desc.URI = URI;
- else {
+ if(Target)
+ MetaKey = string(Target->MetaKey);
+ }
+ else
+ {
Desc.URI = URI + '.' + comprExt;
+ DestFile = DestFile + '.' + comprExt;
+ if(Target)
+ MetaKey = string(Target->MetaKey) + '.' + comprExt;
+ }
+
+ // load the filesize
+ if(MetaIndexParser)
+ {
+ indexRecords::checkSum *Record = MetaIndexParser->Lookup(MetaKey);
+ if(Record)
+ FileSize = Record->Size;
+
+ InitByHashIfNeeded(MetaKey);
}
Desc.Description = URIDesc;
QueueURI(Desc);
}
/*}}}*/
+// AcqIndex::AdjustForByHash - modify URI for by-hash support /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void pkgAcqIndex::InitByHashIfNeeded(const std::string MetaKey)
+{
+ // TODO:
+ // - (maybe?) add support for by-hash into the sources.list as flag
+ // - make apt-ftparchive generate the hashes (and expire?)
+ std::string HostKnob = "APT::Acquire::" + ::URI(Desc.URI).Host + "::By-Hash";
+ if(_config->FindB("APT::Acquire::By-Hash", false) == true ||
+ _config->FindB(HostKnob, false) == true ||
+ MetaIndexParser->GetSupportsAcquireByHash())
+ {
+ indexRecords::checkSum *Record = MetaIndexParser->Lookup(MetaKey);
+ if(Record)
+ {
+ // FIXME: should we really use the best hash here? or a fixed one?
+ const HashString *TargetHash = Record->Hashes.find("");
+ std::string ByHash = "/by-hash/" + TargetHash->HashType() + "/" + TargetHash->HashValue();
+ size_t trailing_slash = Desc.URI.find_last_of("/");
+ Desc.URI = Desc.URI.replace(
+ trailing_slash,
+ Desc.URI.substr(trailing_slash+1).size()+1,
+ ByHash);
+ } else {
+ _error->Warning(
+ "Fetching ByHash requested but can not find record for %s",
+ MetaKey.c_str());
+ }
+ }
+}
+ /*}}}*/
// AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/
// ---------------------------------------------------------------------
/* The only header we use is the last-modified header. */
-string pkgAcqIndex::Custom600Headers()
+string pkgAcqIndex::Custom600Headers() const
{
+ std::string const compExt = CompressionExtension.substr(0, CompressionExtension.find(' '));
string Final = _config->FindDir("Dir::State::lists");
Final += URItoFileName(RealURI);
if (_config->FindB("Acquire::GzipIndexes",false))
- Final += ".gz";
+ Final += compExt;
string msg = "\nIndex-File: true";
- // FIXME: this really should use "IndexTarget::IsOptional()" but that
- // seems to be difficult without breaking ABI
- if (ShortDesc().find("Translation") != 0)
- msg += "\nFail-Ignore: true";
+
struct stat Buf;
if (stat(Final.c_str(),&Buf) == 0)
msg += "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
{
std::string FinalFile = _config->FindDir("Dir::State::lists");
FinalFile += URItoFileName(URI);
- if (_config->FindB("Acquire::GzipIndexes",false) && compExt == "gz")
- FinalFile += ".gz";
+ if (_config->FindB("Acquire::GzipIndexes",false) == true)
+ FinalFile += '.' + compExt;
return FinalFile;
}
/*}}}*/
void pkgAcqIndex::ReverifyAfterIMS(std::string const &FileName)
{
std::string const compExt = CompressionExtension.substr(0, CompressionExtension.find(' '));
- if (_config->FindB("Acquire::GzipIndexes",false) && compExt == "gz")
- DestFile += ".gz";
+ if (_config->FindB("Acquire::GzipIndexes",false) == true)
+ DestFile += compExt;
string FinalFile = GetFinalFilename(RealURI, compExt);
Rename(FinalFile, FileName);
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);
std::string const compExt = CompressionExtension.substr(0, CompressionExtension.find(' '));
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)
{
Desc.URI = RealURI;
RenameOnError(HashSumMismatch);
+ printHashSumComparision(RealURI, ExpectedHashes, Hashes);
return;
}
/* Always verify the index file for correctness (all indexes must
* have a Package field) (LP: #346386) (Closes: #627642)
*/
- FileFd fd(DestFile, FileFd::ReadOnlyGzip);
+ FileFd fd(DestFile, FileFd::ReadOnly, FileFd::Extension);
// Only test for correctness if the file is not empty (empty is ok)
if (fd.Size() > 0)
{
string FinalFile = GetFinalFilename(RealURI, compExt);
Rename(DestFile,FinalFile);
chmod(FinalFile.c_str(),0644);
-
+
/* We restore the original name to DestFile so that the clean operation
will work OK */
DestFile = _config->FindDir("Dir::State::lists") + "partial/";
DestFile += URItoFileName(RealURI);
- if (_config->FindB("Acquire::GzipIndexes",false) && compExt == "gz")
- DestFile += ".gz";
+ if (_config->FindB("Acquire::GzipIndexes",false))
+ DestFile += '.' + compExt;
// Remove the compressed version.
if (Erase == true)
unlink(DestFile.c_str());
+
return;
}
DestFile += ".decomp";
Desc.URI = "copy:" + FileName;
QueueURI(Desc);
+ ActiveSubprocess = "copy";
+#if __GNUC__ >= 4
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
Mode = "copy";
+#if __GNUC__ >= 4
+ #pragma GCC diagnostic pop
+#endif
return;
}
// matching the Release file
if (!Local && StringToBool(LookupTag(Message,"IMS-Hit"),false) == true)
{
+ // set destfile to the final destfile
+ if(_config->FindB("Acquire::GzipIndexes",false) == false)
+ {
+ DestFile = _config->FindDir("Dir::State::lists") + "partial/";
+ DestFile += URItoFileName(RealURI);
+ }
+
ReverifyAfterIMS(FileName);
return;
}
string decompProg;
// If we enable compressed indexes, queue for hash verification
- if (_config->FindB("Acquire::GzipIndexes",false) && compExt == "gz" && !Local)
+ if (_config->FindB("Acquire::GzipIndexes",false))
{
DestFile = _config->FindDir("Dir::State::lists");
- DestFile += URItoFileName(RealURI) + ".gz";
+ DestFile += URItoFileName(RealURI) + '.' + compExt;
Decompression = true;
Desc.URI = "copy:" + FileName;
Desc.URI = decompProg + ":" + FileName;
QueueURI(Desc);
- // FIXME: this points to a c++ string that goes out of scope
- Mode = decompProg.c_str();
+ ActiveSubprocess = decompProg;
+#if __GNUC__ >= 4
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+ Mode = ActiveSubprocess.c_str();
+#if __GNUC__ >= 4
+ #pragma GCC diagnostic pop
+#endif
}
/*}}}*/
// AcqIndexTrans::pkgAcqIndexTrans - Constructor /*{{{*/
/* The Translation file is added to the queue */
pkgAcqIndexTrans::pkgAcqIndexTrans(pkgAcquire *Owner,
string URI,string URIDesc,string ShortDesc)
- : pkgAcqIndex(Owner, URI, URIDesc, ShortDesc, HashString(), "")
+ : pkgAcqIndex(Owner, URI, URIDesc, ShortDesc, HashStringList(), "")
{
}
-pkgAcqIndexTrans::pkgAcqIndexTrans(pkgAcquire *Owner, IndexTarget const *Target,
- HashString const &ExpectedHash, indexRecords const *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));
+ if(Record)
+ FileSize = Record->Size;
}
/*}}}*/
// AcqIndexTrans::Custom600Headers - Insert custom request headers /*{{{*/
// ---------------------------------------------------------------------
-string pkgAcqIndexTrans::Custom600Headers()
+string pkgAcqIndexTrans::Custom600Headers() const
{
+ std::string const compExt = CompressionExtension.substr(0, CompressionExtension.find(' '));
string Final = _config->FindDir("Dir::State::lists");
Final += URItoFileName(RealURI);
-
if (_config->FindB("Acquire::GzipIndexes",false))
- Final += ".gz";
+ Final += compExt;
struct stat Buf;
if (stat(Final.c_str(),&Buf) != 0)
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)
{
Rename(Final,LastGoodSig);
}
+ // we expect the indextargets + one additional Release file
+ ExpectedAdditionalItems = IndexTargets->size() + 1;
+
QueueURI(Desc);
}
/*}}}*/
// 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)
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)
Complete = true;
+ // at this point pkgAcqMetaIndex takes over
+ ExpectedAdditionalItems = 0;
+
// put the last known good file back on i-m-s hit (it will
// be re-verified again)
// Else do nothing, we have the new file in DestFile then
{
string Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI);
+ // at this point pkgAcqMetaIndex takes over
+ ExpectedAdditionalItems = 0;
+
// if we get a network error we fail gracefully
if(Status == StatTransientNetworkError)
{
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/";
Desc.ShortDesc = ShortDesc;
Desc.URI = URI;
+ // we expect more item
+ ExpectedAdditionalItems = IndexTargets->size();
+
QueueURI(Desc);
}
/*}}}*/
// 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);
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
}
else
{
+ // FIXME: move this into pkgAcqMetaClearSig::Done on the next
+ // ABI break
+
+ // if we expect a ClearTextSignature (InRelase), ensure that
+ // this is what we get and if not fail to queue a
+ // Release/Release.gpg, see #346386
+ if (SigFile == DestFile && !StartsWithGPGClearTextSignature(DestFile))
+ {
+ Failed(Message, Cfg);
+ return;
+ }
+
// There was a signature file, so pass it to gpgv for
// verification
-
if (_config->FindB("Debug::pkgAcquire::Auth", false))
std::cerr << "Metaindex acquired, queueing gpg verification ("
<< SigFile << "," << DestFile << ")\n";
AuthPass = true;
Desc.URI = "gpgv:" + SigFile;
QueueURI(Desc);
- Mode = "gpgv";
+ ActiveSubprocess = "gpgv";
+#if __GNUC__ >= 4
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+ Mode = "gpgv";
+#if __GNUC__ >= 4
+ #pragma GCC diagnostic pop
+#endif
return;
}
}
URItoFileName((*Target)->URI);
unlink(index.c_str());
// and also old gzipindexes
- index += ".gz";
- unlink(index.c_str());
+ std::vector<std::string> types = APT::Configuration::getCompressionTypes();
+ for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
+ {
+ index += '.' + (*t);
+ unlink(index.c_str());
+ }
}
}
}
}
- for (vector <struct IndexTarget*>::const_iterator Target = IndexTargets->begin();
+ // at this point the real Items are loaded in the fetcher
+ ExpectedAdditionalItems = 0;
+ for (vector <IndexTarget*>::const_iterator Target = IndexTargets->begin();
Target != IndexTargets->end();
++Target)
{
- HashString ExpectedIndexHash;
+ HashStringList ExpectedIndexHashes;
const indexRecords::checkSum *Record = MetaIndexParser->Lookup((*Target)->MetaKey);
bool compressedAvailable = false;
if (Record == NULL)
}
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());
{
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)->URI, (*Target)->Description,
- (*Target)->ShortDesc, ExpectedIndexHash);
+ new pkgAcqDiffIndex(Owner, *Target, ExpectedIndexHashes, MetaIndexParser);
else
- new pkgAcqIndexTrans(Owner, *Target, ExpectedIndexHash, MetaIndexParser);
+ new pkgAcqIndexTrans(Owner, *Target, ExpectedIndexHashes, MetaIndexParser);
}
continue;
}
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)->URI, (*Target)->Description,
- (*Target)->ShortDesc, ExpectedIndexHash);
+ new pkgAcqDiffIndex(Owner, *Target, ExpectedIndexHashes, MetaIndexParser);
else
- new pkgAcqIndex(Owner, *Target, ExpectedIndexHash, MetaIndexParser);
+ new pkgAcqIndex(Owner, *Target, ExpectedIndexHashes, MetaIndexParser);
}
}
/*}}}*/
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),
{
SigFile = DestFile;
+ // index targets + (worst case:) Release/Release.gpg
+ ExpectedAdditionalItems = IndexTargets->size() + 2;
+
+
// keep the old InRelease around in case of transistent network errors
string const Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI);
if (RealFileExists(Final) == true)
// 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);
/*}}}*/
void pkgAcqMetaClearSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /*{{{*/
{
+ // we failed, we will not get additional items from this method
+ ExpectedAdditionalItems = 0;
+
if (AuthPass == false)
{
// Remove the 'old' InRelease file if we try Release.gpg now as otherwise
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)
{
checking later. */
bool pkgAcqArchive::QueueNext()
{
- string const ForceHash = _config->Find("Acquire::ForceHash");
for (; Vf.end() == false; ++Vf)
{
// Ignore not source sources
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."),
// 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)
RenameOnError(SizeMismatch);
return;
}
-
- // Check the hash
- if(ExpectedHash.toStr() != CalcHash)
+
+ // FIXME: could this empty() check impose *any* sort of security issue?
+ if(ExpectedHashes.usable() && ExpectedHashes != CalcHashes)
{
RenameOnError(HashSumMismatch);
+ printHashSumComparision(DestFile, ExpectedHashes, CalcHashes);
return;
}
/*}}}*/
// AcqArchive::IsTrusted - Determine whether this archive comes from a trusted source /*{{{*/
// ---------------------------------------------------------------------
-APT_PURE bool pkgAcqArchive::IsTrusted()
+APT_PURE bool pkgAcqArchive::IsTrusted() const
{
return Trusted;
}
// 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);
// 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;
}
// 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";
#include <apt-pkg/pkgcachegen.h>
#include <apt-pkg/pkgrecords.h>
#include <apt-pkg/srcrecords.h>
+#include <apt-pkg/sptr.h>
#include <stdio.h>
#include <iostream>
{
string SourcesURI = _config->FindDir("Dir::State::lists") +
URItoFileName(IndexURI("Sources"));
- string SourcesURIgzip = SourcesURI + ".gz";
- if (!FileExists(SourcesURI) && !FileExists(SourcesURIgzip))
- return NULL;
- else if (!FileExists(SourcesURI) && FileExists(SourcesURIgzip))
- SourcesURI = SourcesURIgzip;
-
- return new debSrcRecordParser(SourcesURI,this);
+ std::vector<std::string> types = APT::Configuration::getCompressionTypes();
+ for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
+ {
+ string p;
+ p = SourcesURI + '.' + *t;
+ if (FileExists(p))
+ return new debSrcRecordParser(p, this);
+ }
+ if (FileExists(SourcesURI))
+ return new debSrcRecordParser(SourcesURI, this);
+ return NULL;
}
/*}}}*/
// SourcesIndex::Describe - Give a descriptive path to the index /*{{{*/
inline string debSourcesIndex::IndexFile(const char *Type) const
{
string s = URItoFileName(IndexURI(Type));
- string sgzip = s + ".gz";
- if (!FileExists(s) && FileExists(sgzip))
- return sgzip;
- else
- return s;
+
+ std::vector<std::string> types = APT::Configuration::getCompressionTypes();
+ for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
+ {
+ string p = s + '.' + *t;
+ if (FileExists(p))
+ return p;
+ }
+ return s;
}
string debSourcesIndex::IndexURI(const char *Type) const
inline string debPackagesIndex::IndexFile(const char *Type) const
{
string s =_config->FindDir("Dir::State::lists") + URItoFileName(IndexURI(Type));
- string sgzip = s + ".gz";
- if (!FileExists(s) && FileExists(sgzip))
- return sgzip;
- else
- return s;
+
+ std::vector<std::string> types = APT::Configuration::getCompressionTypes();
+ for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
+ {
+ string p = s + '.' + *t;
+ if (FileExists(p))
+ return p;
+ }
+ return s;
}
string debPackagesIndex::IndexURI(const char *Type) const
{
inline string debTranslationsIndex::IndexFile(const char *Type) const
{
string s =_config->FindDir("Dir::State::lists") + URItoFileName(IndexURI(Type));
- string sgzip = s + ".gz";
- if (!FileExists(s) && FileExists(sgzip))
- return sgzip;
- else
- return s;
+
+ std::vector<std::string> types = APT::Configuration::getCompressionTypes();
+ for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
+ {
+ string p = s + '.' + *t;
+ if (FileExists(p))
+ return p;
+ }
+ return s;
}
string debTranslationsIndex::IndexURI(const char *Type) const
{
pkgCache::PkgFileIterator CFile = Gen.GetCurFile();
CFile->Size = Pkg.FileSize();
CFile->mtime = Pkg.ModificationTime();
- map_ptrloc const storage = Gen.WriteUniqString("now");
+ map_stringitem_t const storage = Gen.StoreString(pkgCacheGenerator::MIXED, "now");
CFile->Archive = storage;
if (Gen.MergeList(Parser) == false)
}
/*}}}*/
+// debDebPkgFile - Single .deb file /*{{{*/
+// ---------------------------------------------------------------------
+debDebPkgFileIndex::debDebPkgFileIndex(std::string DebFile)
+ : pkgIndexFile(true), DebFile(DebFile)
+{
+ DebFileFullPath = flAbsPath(DebFile);
+}
+
+std::string debDebPkgFileIndex::ArchiveURI(std::string /*File*/) const
+{
+ return "file:" + DebFileFullPath;
+}
+
+bool debDebPkgFileIndex::Exists() const
+{
+ return FileExists(DebFile);
+}
+bool debDebPkgFileIndex::Merge(pkgCacheGenerator& Gen, OpProgress* Prog) const
+{
+ if(Prog)
+ Prog->SubProgress(0, "Reading deb file");
+
+ // get the control data out of the deb file vid dpkg -I
+ // ... can I haz libdpkg?
+ Configuration::Item const *Opts = _config->Tree("DPkg::Options");
+ std::string dpkg = _config->Find("Dir::Bin::dpkg","dpkg");
+ std::vector<const char *> Args;
+ Args.push_back(dpkg.c_str());
+ if (Opts != 0)
+ {
+ Opts = Opts->Child;
+ for (; Opts != 0; Opts = Opts->Next)
+ {
+ if (Opts->Value.empty() == true)
+ continue;
+ Args.push_back(Opts->Value.c_str());
+ }
+ }
+ Args.push_back("-I");
+ Args.push_back(DebFile.c_str());
+ Args.push_back("control");
+ Args.push_back(NULL);
+ FileFd PipeFd;
+ pid_t Child;
+ if(Popen((const char**)&Args[0], PipeFd, Child, FileFd::ReadOnly) == false)
+ return _error->Error("Popen failed");
+ // FIXME: static buffer
+ char buf[8*1024];
+ unsigned long long n = 0;
+ if(PipeFd.Read(buf, sizeof(buf)-1, &n) == false)
+ return _error->Errno("read", "Failed to read dpkg pipe");
+ ExecWait(Child, "Popen");
+
+ // now write the control data to a tempfile
+ SPtr<FileFd> DebControl = GetTempFile("deb-file-" + flNotDir(DebFile));
+ if(DebControl == NULL)
+ return false;
+ DebControl->Write(buf, n);
+ // append size of the file
+ FileFd Fd(DebFile, FileFd::ReadOnly);
+ string Size;
+ strprintf(Size, "Size: %llu\n", Fd.Size());
+ DebControl->Write(Size.c_str(), Size.size());
+ // and rewind for the listparser
+ DebControl->Seek(0);
+
+ // and give it to the list parser
+ debDebFileParser Parser(DebControl, DebFile);
+ if(Gen.SelectFile(DebFile, "local", *this) == false)
+ return _error->Error("Problem with SelectFile %s", DebFile.c_str());
+
+ pkgCache::PkgFileIterator File = Gen.GetCurFile();
+ File->Size = DebControl->Size();
+ File->mtime = DebControl->ModificationTime();
+
+ if (Gen.MergeList(Parser) == false)
+ return _error->Error("Problem with MergeLister for %s", DebFile.c_str());
+
+ return true;
+}
+pkgCache::PkgFileIterator debDebPkgFileIndex::FindInCache(pkgCache &Cache) const
+{
+ pkgCache::PkgFileIterator File = Cache.FileBegin();
+ for (; File.end() == false; ++File)
+ {
+ if (File.FileName() == NULL || DebFile != File.FileName())
+ continue;
+
+ return File;
+ }
+
+ return File;
+}
+unsigned long debDebPkgFileIndex::Size() const
+{
+ struct stat buf;
+ if(stat(DebFile.c_str(), &buf) != 0)
+ return 0;
+ return buf.st_size;
+}
+ /*}}}*/
+
+// debDscFileIndex stuff
+debDscFileIndex::debDscFileIndex(std::string &DscFile)
+ : pkgIndexFile(true), DscFile(DscFile)
+{
+}
+
+bool debDscFileIndex::Exists() const
+{
+ return FileExists(DscFile);
+}
+
+unsigned long debDscFileIndex::Size() const
+{
+ struct stat buf;
+ if(stat(DscFile.c_str(), &buf) == 0)
+ return buf.st_size;
+ return 0;
+}
+
+// DscFileIndex::CreateSrcParser - Get a parser for the .dsc file /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+pkgSrcRecords::Parser *debDscFileIndex::CreateSrcParser() const
+{
+ if (!FileExists(DscFile))
+ return NULL;
+
+ return new debDscRecordParser(DscFile,this);
+}
+ /*}}}*/
+
+
+
+
+// ---------------------------------------------------------------------
// Index File types for Debian /*{{{*/
class debIFTypeSrc : public pkgIndexFile::Type
{
};
debIFTypeStatus() {Label = "Debian dpkg status file";};
};
+class debIFTypeDebPkgFile : public pkgIndexFile::Type
+{
+ public:
+ virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const
+ {
+ return new debDebFileRecordParser(File.FileName(),*File.Cache());
+ };
+ debIFTypeDebPkgFile() {Label = "deb Package file";};
+};
+class debIFTypeDscFile : public pkgIndexFile::Type
+{
+ public:
+ virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string DscFile) const
+ {
+ return new debDscRecordParser(DscFile, NULL);
+ };
+ debIFTypeDscFile() {Label = "dsc File Source Index";};
+};
+class debIFTypeDebianSourceDir : public pkgIndexFile::Type
+{
+ public:
+ virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string SourceDir) const
+ {
+ return new debDscRecordParser(SourceDir + string("/debian/control"), NULL);
+ };
+ debIFTypeDebianSourceDir() {Label = "debian/control File Source Index";};
+};
+
static debIFTypeSrc _apt_Src;
static debIFTypePkg _apt_Pkg;
static debIFTypeTrans _apt_Trans;
static debIFTypeStatus _apt_Status;
+static debIFTypeDebPkgFile _apt_DebPkgFile;
+// file based pseudo indexes
+static debIFTypeDscFile _apt_DscFile;
+static debIFTypeDebianSourceDir _apt_DebianSourceDir;
const pkgIndexFile::Type *debSourcesIndex::GetType() const
{
{
return &_apt_Status;
}
-
+const pkgIndexFile::Type *debDebPkgFileIndex::GetType() const
+{
+ return &_apt_DebPkgFile;
+}
+const pkgIndexFile::Type *debDscFileIndex::GetType() const
+{
+ return &_apt_DscFile;
+}
+const pkgIndexFile::Type *debDebianSourceDirIndex::GetType() const
+{
+ return &_apt_DebianSourceDir;
+}
/*}}}*/
// FindSrc - Find a source record /*{{{*/
// ---------------------------------------------------------------------
/* */
-static pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs,
+static pkgSrcRecords::Parser *FindSrc(const char *Name,
pkgSrcRecords &SrcRecs,string &Src,
CacheFile &CacheFile)
{
(VF.File().Archive() != 0 && VF.File().Archive() == RelTag) ||
(VF.File().Codename() != 0 && VF.File().Codename() == RelTag))
{
- pkgRecords::Parser &Parse = Recs.Lookup(VF);
- Src = Parse.SourcePkg();
- // no SourcePkg name, so it is the "binary" name
- if (Src.empty() == true)
- Src = TmpSrc;
+ Src = Ver.SourcePkgName();
// the Version we have is possibly fuzzy or includes binUploads,
- // so we use the Version of the SourcePkg (empty if same as package)
- VerTag = Parse.SourceVer();
- if (VerTag.empty() == true)
- VerTag = Ver.VerStr();
+ // so we use the Version of the SourcePkg
+ VerTag = Ver.SourceVerStr();
break;
}
}
pkgCache::VerIterator Ver = Cache->GetCandidateVer(Pkg);
if (Ver.end() == false)
{
- pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
- Src = Parse.SourcePkg();
- if (VerTag.empty() == true)
- VerTag = Parse.SourceVer();
+ if (strcmp(Ver.SourcePkgName(),Ver.ParentPkg().Name()) != 0)
+ Src = Ver.SourcePkgName();
+ if (VerTag.empty() == true && strcmp(Ver.SourceVerStr(),Ver.VerStr()) != 0)
+ VerTag = Ver.SourceVerStr();
}
}
}
}
// Now upgrade everything
- if (pkgAllUpgrade(Cache) == false)
+ if (APT::Upgrade::Upgrade(Cache, APT::Upgrade::FORBID_REMOVE_PACKAGES | APT::Upgrade::FORBID_INSTALL_NEW_PACKAGES) == false)
{
ShowBroken(c1out,Cache,false);
return _error->Error(_("Internal error, problem resolver broke stuff"));
static bool DoClean(CommandLine &)
{
std::string const archivedir = _config->FindDir("Dir::Cache::archives");
- std::string const pkgcache = _config->FindFile("Dir::cache::pkgcache");
- std::string const srcpkgcache = _config->FindFile("Dir::cache::srcpkgcache");
+ std::string const listsdir = _config->FindDir("Dir::state::lists");
if (_config->FindB("APT::Get::Simulate") == true)
{
+ std::string const pkgcache = _config->FindFile("Dir::cache::pkgcache");
+ std::string const srcpkgcache = _config->FindFile("Dir::cache::srcpkgcache");
cout << "Del " << archivedir << "* " << archivedir << "partial/*"<< endl
+ << "Del " << listsdir << "partial/*" << endl
<< "Del " << pkgcache << " " << srcpkgcache << endl;
return true;
}
-
+
+ bool const NoLocking = _config->FindB("Debug::NoLocking",false);
// Lock the archive directory
FileFd Lock;
- if (_config->FindB("Debug::NoLocking",false) == false)
+ if (NoLocking == false)
{
int lock_fd = GetLock(archivedir + "lock");
if (lock_fd < 0)
- return _error->Error(_("Unable to lock the download directory"));
+ return _error->Error(_("Unable to lock directory %s"), archivedir.c_str());
Lock.Fd(lock_fd);
}
-
+
pkgAcquire Fetcher;
Fetcher.Clean(archivedir);
Fetcher.Clean(archivedir + "partial/");
+ if (NoLocking == false)
+ {
+ Lock.Close();
+ int lock_fd = GetLock(listsdir + "lock");
+ if (lock_fd < 0)
+ return _error->Error(_("Unable to lock directory %s"), listsdir.c_str());
+ Lock.Fd(lock_fd);
+ }
+
+ Fetcher.Clean(listsdir + "partial/");
+
pkgCacheFile::RemoveCaches();
return true;
APT::CacheSetHelper helper(c0out);
APT::VersionSet verset = APT::VersionSet::FromCommandLine(Cache,
- CmdL.FileList + 1, APT::VersionSet::CANDIDATE, helper);
+ CmdL.FileList + 1, APT::CacheSetHelper::CANDIDATE, helper);
if (verset.empty() == true)
return false;
AcqTextStatus Stat(ScreenWidth, _config->FindI("quiet", 0));
pkgAcquire Fetcher;
- if (Fetcher.Setup(&Stat) == false)
+ if (Fetcher.Setup(&Stat, "", false) == false)
return false;
pkgRecords Recs(Cache);
{
pkgAcquire::UriIterator I = Fetcher.UriBegin();
for (; I != Fetcher.UriEnd(); ++I)
- cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
+ cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl;
return true;
}
pkgSourceList *List = Cache.GetSourceList();
// Create the text record parsers
- pkgRecords Recs(Cache);
pkgSrcRecords SrcRecs(*List);
if (_error->PendingError() == true)
return false;
for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
{
string Src;
- pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,Cache);
+ pkgSrcRecords::Parser *Last = FindSrc(*I,SrcRecs,Src,Cache);
if (Last == 0) {
return _error->Error(_("Unable to find a source package for %s"),Src.c_str());
queued.insert(Last->Index().ArchiveURI(I->Path));
// check if we have a file with that md5 sum already localy
- if(!I->MD5Hash.empty() && FileExists(flNotDir(I->Path)))
- {
- FileFd Fd(flNotDir(I->Path), FileFd::ReadOnly);
- MD5Summation sum;
- sum.AddFD(Fd.Fd(), Fd.Size());
- Fd.Close();
- if((string)sum.Result() == I->MD5Hash)
+ 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->MD5Hash,I->Size,
- Last->Index().SourceInfo(*Last,*I),Src);
+ I->Hashes, I->Size, Last->Index().SourceInfo(*Last,*I), Src);
}
}
pkgSourceList *List = Cache.GetSourceList();
// Create the text record parsers
- pkgRecords Recs(Cache);
pkgSrcRecords SrcRecs(*List);
if (_error->PendingError() == true)
return false;
for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
{
string Src;
- pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,Cache);
+ pkgSrcRecords::Parser *Last = 0;
+
+ // an unpacked debian source tree
+ using APT::String::Startswith;
+ if ((Startswith(*I, "./") || Startswith(*I, "/")) &&
+ DirectoryExists(*I))
+ {
+ ioprintf(c1out, _("Note, using directory '%s' to get the build dependencies\n"), *I);
+ // FIXME: how can we make this more elegant?
+ std::string TypeName = "debian/control File Source Index";
+ pkgIndexFile::Type *Type = pkgIndexFile::Type::GetType(TypeName.c_str());
+ if(Type != NULL)
+ Last = Type->CreateSrcPkgParser(*I);
+ }
+ // if its a local file (e.g. .dsc) use this
+ else if (FileExists(*I))
+ {
+ ioprintf(c1out, _("Note, using file '%s' to get the build dependencies\n"), *I);
+
+ // see if we can get a parser for this pkgIndexFile type
+ string TypeName = flExtension(*I) + " File Source Index";
+ pkgIndexFile::Type *Type = pkgIndexFile::Type::GetType(TypeName.c_str());
+ if(Type != NULL)
+ Last = Type->CreateSrcPkgParser(*I);
+ } else {
+ // normal case, search the cache for the source file
+ Last = FindSrc(*I,SrcRecs,Src,Cache);
+ }
+
if (Last == 0)
return _error->Error(_("Unable to find a source package for %s"),Src.c_str());
}
else if (Last->BuildDepends(BuildDeps, _config->FindB("APT::Get::Arch-Only", false), StripMultiArch) == false)
return _error->Error(_("Unable to get build-dependency information for %s"),Src.c_str());
-
+
// Also ensure that build-essential packages are present
Configuration::Item const *Opts = _config->Tree("APT::Build-Essential");
if (Opts)
* pool/ next to the deb itself)
* Example return: "pool/main/a/apt/apt_0.8.8ubuntu3"
*/
-static string GetChangelogPath(CacheFile &Cache,
- pkgCache::PkgIterator Pkg,
+static string GetChangelogPath(CacheFile &Cache,
pkgCache::VerIterator Ver)
{
- string path;
-
pkgRecords Recs(Cache);
pkgRecords::Parser &rec=Recs.Lookup(Ver.FileList());
- string srcpkg = rec.SourcePkg().empty() ? Pkg.Name() : rec.SourcePkg();
- string ver = Ver.VerStr();
- // if there is a source version it always wins
- if (rec.SourceVer() != "")
- ver = rec.SourceVer();
- path = flNotFile(rec.FileName());
- path += srcpkg + "_" + StripEpoch(ver);
+ string path = flNotFile(rec.FileName());
+ path.append(Ver.SourcePkgName());
+ path.append("_");
+ path.append(StripEpoch(Ver.SourceVerStr()));
return path;
}
/*}}}*/
* http://packages.medibuntu.org/pool/non-free/m/mplayer/mplayer_1.0~rc4~try1.dsfg1-1ubuntu1+medibuntu1.changelog
*/
static bool GuessThirdPartyChangelogUri(CacheFile &Cache,
- pkgCache::PkgIterator Pkg,
pkgCache::VerIterator Ver,
string &out_uri)
{
return false;
// get archive uri for the binary deb
- string path_without_dot_changelog = GetChangelogPath(Cache, Pkg, Ver);
+ string path_without_dot_changelog = GetChangelogPath(Cache, Ver);
out_uri = index->ArchiveURI(path_without_dot_changelog + ".changelog");
// now strip away the filename and add srcpkg_srcver.changelog
* GuessThirdPartyChangelogUri for details how)
*/
{
- string path;
- string descr;
- string server;
- string changelog_uri;
-
- // data structures we need
- pkgCache::PkgIterator Pkg = Ver.ParentPkg();
-
// make the server root configurable
- server = _config->Find("Apt::Changelogs::Server",
+ string const server = _config->Find("Apt::Changelogs::Server",
"http://packages.debian.org/changelogs");
- path = GetChangelogPath(CacheFile, Pkg, Ver);
+ string const path = GetChangelogPath(CacheFile, Ver);
+ string changelog_uri;
strprintf(changelog_uri, "%s/%s/changelog", server.c_str(), path.c_str());
if (_config->FindB("APT::Get::Print-URIs", false) == true)
{
std::cout << '\'' << changelog_uri << '\'' << std::endl;
return true;
}
+ pkgCache::PkgIterator const Pkg = Ver.ParentPkg();
+ string descr;
strprintf(descr, _("Changelog for %s (%s)"), Pkg.Name(), changelog_uri.c_str());
// queue it
new pkgAcqFile(&Fetcher, changelog_uri, "", 0, descr, Pkg.Name(), "ignored", targetfile);
if (!FileExists(targetfile))
{
string third_party_uri;
- if (GuessThirdPartyChangelogUri(CacheFile, Pkg, Ver, third_party_uri))
+ if (GuessThirdPartyChangelogUri(CacheFile, Ver, third_party_uri))
{
strprintf(descr, _("Changelog for %s (%s)"), Pkg.Name(), third_party_uri.c_str());
new pkgAcqFile(&Fetcher, third_party_uri, "", 0, descr, Pkg.Name(), "ignored", targetfile);
APT::CacheSetHelper helper(c0out);
APT::VersionList verset = APT::VersionList::FromCommandLine(Cache,
- CmdL.FileList + 1, APT::VersionList::CANDIDATE, helper);
+ CmdL.FileList + 1, APT::CacheSetHelper::CANDIDATE, helper);
if (verset.empty() == true)
return false;
pkgAcquire Fetcher;
}
AcqTextStatus Stat(ScreenWidth, _config->FindI("quiet",0));
- Fetcher.Setup(&Stat);
+ if (Fetcher.Setup(&Stat, "",false) == false)
+ return false;
bool const downOnly = _config->FindB("APT::Get::Download-Only", false);