##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/acquire-item.h"
-#endif
#include <apt-pkg/acquire-item.h>
#include <apt-pkg/configuration.h>
#include <apt-pkg/sourcelist.h>
{
Status = StatIdle;
ErrorText = LookupTag(Message,"Message");
+ UsedMirror = LookupTag(Message,"UsedMirror");
if (QueueCounter <= 1)
{
/* This indicates that the file is not available right now but might
Status = StatError;
Dequeue();
}
+
+ // report mirror failure back to LP if we actually use a mirror
+ string FailReason = LookupTag(Message, "FailReason");
+ if(FailReason.size() != 0)
+ ReportMirrorFailure(FailReason);
+ else
+ ReportMirrorFailure(ErrorText);
}
/*}}}*/
// Acquire::Item::Start - Item has begun to download /*{{{*/
// Acquire::Item::Done - Item downloaded OK /*{{{*/
// ---------------------------------------------------------------------
/* */
-void pkgAcquire::Item::Done(string Message,unsigned long Size,string,
+void pkgAcquire::Item::Done(string Message,unsigned long Size,string Hash,
pkgAcquire::MethodConfig *Cnf)
{
// We just downloaded something..
string FileName = LookupTag(Message,"Filename");
- // we only inform the Log class if it was actually not a local thing
+ UsedMirror = LookupTag(Message,"UsedMirror");
if (Complete == false && !Local && FileName == DestFile)
{
if (Owner->Log != 0)
if (FileSize == 0)
FileSize= Size;
-
Status = StatDone;
ErrorText = string();
Owner->Dequeue(this);
}
/*}}}*/
+void pkgAcquire::Item::ReportMirrorFailure(string FailCode)
+{
+ // we only act if a mirror was used at all
+ if(UsedMirror.empty())
+ return;
+#if 0
+ std::cerr << "\nReportMirrorFailure: "
+ << UsedMirror
+ << " Uri: " << DescURI()
+ << " FailCode: "
+ << FailCode << std::endl;
+#endif
+ const char *Args[40];
+ unsigned int i = 0;
+ string report = _config->Find("Methods::Mirror::ProblemReporting",
+ "/usr/lib/apt/apt-report-mirror-failure");
+ if(!FileExists(report))
+ return;
+ Args[i++] = report.c_str();
+ Args[i++] = UsedMirror.c_str();
+ Args[i++] = DescURI().c_str();
+ Args[i++] = FailCode.c_str();
+ Args[i++] = NULL;
+ pid_t pid = ExecFork();
+ if(pid < 0)
+ {
+ _error->Error("ReportMirrorFailure Fork failed");
+ return;
+ }
+ else if(pid == 0)
+ {
+ execvp(Args[0], (char**)Args);
+ std::cerr << "Could not exec " << Args[0] << std::endl;
+ _exit(100);
+ }
+ if(!ExecWait(pid, "report-mirror-failure"))
+ {
+ _error->Warning("Couldn't report problem to '%s'",
+ _config->Find("Methods::Mirror::ProblemReporting").c_str());
+ }
+}
+
+
// AcqDiffIndex::AcqDiffIndex - Constructor
// ---------------------------------------------------------------------
*/
pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner,
string URI,string URIDesc,string ShortDesc,
- string ExpectedMD5)
- : Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5), Description(URIDesc)
+ HashString ExpectedHash)
+ : Item(Owner), RealURI(URI), ExpectedHash(ExpectedHash),
+ Description(URIDesc)
{
Debug = _config->FindB("Debug::pkgAcquire::Diffs",false);
if(found)
{
// queue the diffs
- int last_space = Description.rfind(" ");
- if(last_space != string::npos)
- Description.erase(last_space, Description.size()-last_space);
+ string::size_type last_space = Description.rfind(" ");
+ if(last_space != string::npos)
+ Description.erase(last_space, Description.size()-last_space);
new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc,
- ExpectedMD5, available_patches);
+ ExpectedHash, available_patches);
Complete = false;
Status = StatDone;
Dequeue();
return true;
}
}
-
+
// Nothing found, report and return false
// Failing here is ok, if we return false later, the full
// IndexFile is queued
<< "Falling back to normal index file aquire" << std::endl;
new pkgAcqIndex(Owner, RealURI, Description, Desc.ShortDesc,
- ExpectedMD5);
+ ExpectedHash);
Complete = false;
Status = StatDone;
*/
pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire *Owner,
string URI,string URIDesc,string ShortDesc,
- string ExpectedMD5, vector<DiffInfo> diffs)
- : Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5),
+ HashString ExpectedHash,
+ vector<DiffInfo> diffs)
+ : Item(Owner), RealURI(URI), ExpectedHash(ExpectedHash),
available_patches(diffs)
{
std::clog << "pkgAcqIndexDiffs failed: " << Desc.URI << std::endl
<< "Falling back to normal index file aquire" << std::endl;
new pkgAcqIndex(Owner, RealURI, Description,Desc.ShortDesc,
- ExpectedMD5);
+ ExpectedHash);
Finish();
}
DestFile = _config->FindDir("Dir::State::lists");
DestFile += URItoFileName(RealURI);
- // do the final md5sum checking
- MD5Summation sum;
- FileFd Fd(DestFile, FileFd::ReadOnly);
- sum.AddFD(Fd.Fd(), Fd.Size());
- Fd.Close();
- string MD5 = (string)sum.Result();
-
- if (!ExpectedMD5.empty() && MD5 != ExpectedMD5)
+ if(!ExpectedHash.empty() && !ExpectedHash.VerifyFile(DestFile))
{
Status = StatAuthError;
ErrorText = _("MD5Sum mismatch");
// queue the right diff
Desc.URI = string(RealURI) + ".diff/" + available_patches[0].file + ".gz";
Desc.Description = Description + " " + available_patches[0].file + string(".pdiff");
-
DestFile = _config->FindDir("Dir::State::lists") + "partial/";
DestFile += URItoFileName(RealURI + ".diff/" + available_patches[0].file);
// see if there is more to download
if(available_patches.size() > 0) {
new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc,
- ExpectedMD5, available_patches);
+ ExpectedHash, available_patches);
return Finish();
} else
return Finish(true);
instantiated to fetch the revision file */
pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner,
string URI,string URIDesc,string ShortDesc,
- string ExpectedMD5, string comprExt)
- : Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5)
+ HashString ExpectedHash, string comprExt)
+ : Item(Owner), RealURI(URI), ExpectedHash(ExpectedHash)
{
Decompression = false;
Erase = false;
struct stat Buf;
if (stat(Final.c_str(),&Buf) != 0)
return "\nIndex-File: true";
-
return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
}
/*}}}*/
void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
{
-
// no .bz2 found, retry with .gz
if(Desc.URI.substr(Desc.URI.size()-3) == "bz2") {
Desc.URI = Desc.URI.substr(0,Desc.URI.size()-3) + "gz";
// retry with a gzip one
new pkgAcqIndex(Owner, RealURI, Desc.Description,Desc.ShortDesc,
- ExpectedMD5, string(".gz"));
+ ExpectedHash, string(".gz"));
Status = StatDone;
Complete = false;
Dequeue();
to the uncompressed version of the file. If this is so the file
is copied into the partial directory. In all other cases the file
is decompressed with a gzip uri. */
-void pkgAcqIndex::Done(string Message,unsigned long Size,string MD5,
+void pkgAcqIndex::Done(string Message,unsigned long Size,string Hash,
pkgAcquire::MethodConfig *Cfg)
{
- Item::Done(Message,Size,MD5,Cfg);
+ Item::Done(Message,Size,Hash,Cfg);
if (Decompression == true)
{
if (_config->FindB("Debug::pkgAcquire::Auth", false))
{
- std::cerr << std::endl << RealURI << ": Computed MD5: " << MD5;
- std::cerr << " Expected MD5: " << ExpectedMD5 << std::endl;
- }
-
- if (MD5.empty())
- {
- MD5Summation sum;
- FileFd Fd(DestFile, FileFd::ReadOnly);
- sum.AddFD(Fd.Fd(), Fd.Size());
- Fd.Close();
- MD5 = (string)sum.Result();
+ std::cerr << std::endl << RealURI << ": Computed Hash: " << Hash;
+ std::cerr << " Expected Hash: " << ExpectedHash.toStr() << std::endl;
}
- if (!ExpectedMD5.empty() && MD5 != ExpectedMD5)
+ if (!ExpectedHash.empty() && ExpectedHash.toStr() != Hash)
{
Status = StatAuthError;
- ErrorText = _("MD5Sum mismatch");
+ ErrorText = _("Hash Sum mismatch");
Rename(DestFile,DestFile + ".FAILED");
+ ReportMirrorFailure("HashChecksumFailure");
return;
}
// Done, move it into position
// The files timestamp matches
if (StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false) == true)
return;
-
Decompression = true;
Local = true;
DestFile += ".decomp";
Local = true;
string compExt = Desc.URI.substr(Desc.URI.size()-3);
- char *decompProg;
+ const char *decompProg;
if(compExt == "bz2")
decompProg = "bzip2";
else if(compExt == ".gz")
// ---------------------------------------------------------------------
/* The Translation file is added to the queue */
pkgAcqIndexTrans::pkgAcqIndexTrans(pkgAcquire *Owner,
- string URI,string URIDesc,string ShortDesc) :
- pkgAcqIndex(Owner, URI, URIDesc, ShortDesc, "", "")
+ string URI,string URIDesc,string ShortDesc)
+ : pkgAcqIndex(Owner, URI, URIDesc, ShortDesc, HashString(), "")
{
}
if(Status == StatTransientNetworkError)
{
Item::Failed(Message,Cnf);
- // move the sigfile back on network failures (and re-authenticated?)
+ // move the sigfile back on transient network failures
if(FileExists(DestFile))
Rename(DestFile,Final);
string SigFile,
const vector<struct IndexTarget*>* IndexTargets,
indexRecords* MetaIndexParser) :
- Item(Owner), RealURI(URI), SigFile(SigFile), AuthPass(false),
- MetaIndexParser(MetaIndexParser), IndexTargets(IndexTargets), IMSHit(false)
+ Item(Owner), RealURI(URI), SigFile(SigFile), IndexTargets(IndexTargets),
+ MetaIndexParser(MetaIndexParser), AuthPass(false), IMSHit(false)
{
DestFile = _config->FindDir("Dir::State::lists") + "partial/";
DestFile += URItoFileName(URI);
return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
}
-void pkgAcqMetaIndex::Done(string Message,unsigned long Size,string MD5,
+void pkgAcqMetaIndex::Done(string Message,unsigned long Size,string Hash,
pkgAcquire::MethodConfig *Cfg)
{
- Item::Done(Message,Size,MD5,Cfg);
+ Item::Done(Message,Size,Hash,Cfg);
// MetaIndexes are done in two passes: one to download the
// metaindex with an appropriate method, and a second to verify it
// see if the download was a IMSHit
IMSHit = StringToBool(LookupTag(Message,"IMS-Hit"),false);
-
Complete = true;
string FinalFile = _config->FindDir("Dir::State::lists");
FinalFile += URItoFileName(RealURI);
- // The files timestamp matches
- if (StringToBool(LookupTag(Message,"IMS-Hit"),false) == false)
- {
- // Move it into position
+ // If we get a IMS hit we can remove the empty file in partial
+ // othersie we move the file in place
+ if (IMSHit)
+ unlink(DestFile.c_str());
+ else
Rename(DestFile,FinalFile);
- }
+
chmod(FinalFile.c_str(),0644);
DestFile = FinalFile;
}
Target != IndexTargets->end();
Target++)
{
- string ExpectedIndexMD5;
+ HashString ExpectedIndexHash;
if (verify)
{
const indexRecords::checkSum *Record = MetaIndexParser->Lookup((*Target)->MetaKey);
+ (*Target)->MetaKey + " in Meta-index file (malformed Release file?)";
return;
}
- ExpectedIndexMD5 = Record->MD5Hash;
+ ExpectedIndexHash = Record->Hash;
if (_config->FindB("Debug::pkgAcquire::Auth", false))
{
std::cerr << "Queueing: " << (*Target)->URI << std::endl;
- std::cerr << "Expected MD5: " << ExpectedIndexMD5 << std::endl;
+ std::cerr << "Expected Hash: " << ExpectedIndexHash.toStr() << std::endl;
}
- if (ExpectedIndexMD5.empty())
+ if (ExpectedIndexHash.empty())
{
Status = StatAuthError;
- ErrorText = "Unable to find MD5 sum for "
+ ErrorText = "Unable to find hash sum for "
+ (*Target)->MetaKey + " in Meta-index file";
return;
}
// Queue Packages file (either diff or full packages files, depending
// on the users option)
- if(_config->FindB("Acquire::PDiffs",true) == true)
+ if(_config->FindB("Acquire::PDiffs",false) == true)
new pkgAcqDiffIndex(Owner, (*Target)->URI, (*Target)->Description,
- (*Target)->ShortDesc, ExpectedIndexMD5);
+ (*Target)->ShortDesc, ExpectedIndexHash);
else
new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description,
- (*Target)->ShortDesc, ExpectedIndexMD5);
+ (*Target)->ShortDesc, ExpectedIndexHash);
}
}
}
// gpgv method failed
+ ReportMirrorFailure("GPGFailure");
_error->Warning("GPG error: %s: %s",
Desc.Description.c_str(),
LookupTag(Message,"Message").c_str());
return false;
string PkgFile = Parse.FileName();
- MD5 = Parse.MD5Hash();
+ if(Parse.SHA256Hash() != "")
+ ExpectedHash = HashString("SHA256", Parse.SHA256Hash());
+ else if (Parse.SHA1Hash() != "")
+ ExpectedHash = HashString("SHA1", Parse.SHA1Hash());
+ else
+ ExpectedHash = HashString("MD5Sum", Parse.MD5Hash());
if (PkgFile.empty() == true)
return _error->Error(_("The package index files are corrupted. No Filename: "
"field for package %s."),
// AcqArchive::Done - Finished fetching /*{{{*/
// ---------------------------------------------------------------------
/* */
-void pkgAcqArchive::Done(string Message,unsigned long Size,string Md5Hash,
+void pkgAcqArchive::Done(string Message,unsigned long Size,string CalcHash,
pkgAcquire::MethodConfig *Cfg)
{
- Item::Done(Message,Size,Md5Hash,Cfg);
+ Item::Done(Message,Size,CalcHash,Cfg);
// Check the size
if (Size != Version->Size)
return;
}
- // Check the md5
- if (Md5Hash.empty() == false && MD5.empty() == false)
+ // Check the hash
+ if(ExpectedHash.toStr() != CalcHash)
{
- if (Md5Hash != MD5)
- {
- Status = StatError;
- ErrorText = _("MD5Sum mismatch");
- if(FileExists(DestFile))
- Rename(DestFile,DestFile + ".FAILED");
- return;
- }
+ Status = StatError;
+ ErrorText = _("Hash Sum mismatch");
+ if(FileExists(DestFile))
+ Rename(DestFile,DestFile + ".FAILED");
+ return;
}
// Grab the output filename
// AcqFile::pkgAcqFile - Constructor /*{{{*/
// ---------------------------------------------------------------------
/* The file is added to the queue */
-pkgAcqFile::pkgAcqFile(pkgAcquire *Owner,string URI,string MD5,
+pkgAcqFile::pkgAcqFile(pkgAcquire *Owner,string URI,string Hash,
unsigned long Size,string Dsc,string ShortDesc,
const string &DestDir, const string &DestFilename) :
- Item(Owner), Md5Hash(MD5)
+ Item(Owner), ExpectedHash(Hash)
{
Retries = _config->FindI("Acquire::Retries",0);
// AcqFile::Done - Item downloaded OK /*{{{*/
// ---------------------------------------------------------------------
/* */
-void pkgAcqFile::Done(string Message,unsigned long Size,string MD5,
+void pkgAcqFile::Done(string Message,unsigned long Size,string CalcHash,
pkgAcquire::MethodConfig *Cnf)
{
- // Check the md5
- if (Md5Hash.empty() == false && MD5.empty() == false)
+ Item::Done(Message,Size,CalcHash,Cnf);
+
+ // Check the hash
+ if(!ExpectedHash.empty() && ExpectedHash.toStr() != CalcHash)
{
- if (Md5Hash != MD5)
- {
- Status = StatError;
- ErrorText = "MD5Sum mismatch";
- Rename(DestFile,DestFile + ".FAILED");
- return;
- }
+ Status = StatError;
+ ErrorText = "Hash Sum mismatch";
+ Rename(DestFile,DestFile + ".FAILED");
+ return;
}
- Item::Done(Message,Size,MD5,Cnf);
-
string FileName = LookupTag(Message,"Filename");
if (FileName.empty() == true)
{