}
/*}}}*/
+static void ReportMirrorFailureToCentral(pkgAcquire::Item const &I, std::string const &FailCode, std::string const &Details)/*{{{*/
+{
+ // we only act if a mirror was used at all
+ if(I.UsedMirror.empty())
+ return;
+#if 0
+ std::cerr << "\nReportMirrorFailure: "
+ << UsedMirror
+ << " Uri: " << DescURI()
+ << " FailCode: "
+ << FailCode << std::endl;
+#endif
+ string const report = _config->Find("Methods::Mirror::ProblemReporting",
+ "/usr/lib/apt/apt-report-mirror-failure");
+ if(!FileExists(report))
+ return;
+
+ std::vector<char const*> const Args = {
+ report.c_str(),
+ I.UsedMirror.c_str(),
+ I.DescURI().c_str(),
+ FailCode.c_str(),
+ Details.c_str(),
+ NULL
+ };
+
+ pid_t pid = ExecFork();
+ if(pid < 0)
+ {
+ _error->Error("ReportMirrorFailure Fork failed");
+ return;
+ }
+ else if(pid == 0)
+ {
+ execvp(Args[0], (char**)Args.data());
+ 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'", report.c_str());
+}
+ /*}}}*/
+
static bool MessageInsecureRepository(bool const isError, std::string const &msg)/*{{{*/
{
if (isError)
Status = StatDone;
return false;
}
+ // If we got the InRelease file via a mirror, pick all indexes directly from this mirror, too
+ if (TransactionManager != nullptr && TransactionManager->BaseURI.empty() == false &&
+ URI::SiteOnly(Item.URI) != URI::SiteOnly(TransactionManager->BaseURI))
+ {
+ // this ensures we rewrite only once and only the first step
+ auto const OldBaseURI = Target.Option(IndexTarget::BASE_URI);
+ if (APT::String::Startswith(Item.URI, OldBaseURI))
+ {
+ auto const ExtraPath = Item.URI.substr(OldBaseURI.length());
+ Item.URI = flCombine(TransactionManager->BaseURI, ExtraPath);
+ UsedMirror = TransactionManager->UsedMirror;
+ if (Item.Description.find(" ") != string::npos)
+ Item.Description.replace(0, Item.Description.find(" "), UsedMirror);
+ }
+ }
return pkgAcquire::Item::QueueURI(Item);
}
/* The transition manager InRelease itself (or its older sisters-in-law
fetch this object */
void pkgAcquire::Item::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf)
{
- if(ErrorText.empty())
- ErrorText = LookupTag(Message,"Message");
if (QueueCounter <= 1)
{
/* This indicates that the file is not available right now but might
}
string const FailReason = LookupTag(Message, "FailReason");
- if (FailReason == "MaximumSizeExceeded")
- RenameOnError(MaximumSizeExceeded);
+ enum { MAXIMUM_SIZE_EXCEEDED, HASHSUM_MISMATCH, OTHER } failreason = OTHER;
+ if ( FailReason == "MaximumSizeExceeded")
+ failreason = MAXIMUM_SIZE_EXCEEDED;
else if (Status == StatAuthError)
- RenameOnError(HashSumMismatch);
+ failreason = HASHSUM_MISMATCH;
+
+ if(ErrorText.empty())
+ {
+ if (Status == StatAuthError)
+ {
+ std::ostringstream out;
+ switch (failreason)
+ {
+ case HASHSUM_MISMATCH:
+ out << _("Hash Sum mismatch") << std::endl;
+ break;
+ case MAXIMUM_SIZE_EXCEEDED:
+ case OTHER:
+ out << LookupTag(Message, "Message") << std::endl;
+ break;
+ }
+ auto const ExpectedHashes = GetExpectedHashes();
+ if (ExpectedHashes.empty() == false)
+ {
+ out << "Hashes of expected file:" << std::endl;
+ for (auto const &hs: ExpectedHashes)
+ out << " - " << hs.toStr() << std::endl;
+ }
+ if (failreason == HASHSUM_MISMATCH)
+ {
+ out << "Hashes of received file:" << std::endl;
+ for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type)
+ {
+ std::string const tagname = std::string(*type) + "-Hash";
+ std::string const hashsum = LookupTag(Message, tagname.c_str());
+ if (hashsum.empty() == false)
+ out << " - " << HashString(*type, hashsum).toStr() << std::endl;
+ }
+ out << "Last modification reported: " << LookupTag(Message, "Last-Modified", "<none>") << std::endl;
+ }
+ ErrorText = out.str();
+ }
+ else
+ ErrorText = LookupTag(Message,"Message");
+ }
+
+ switch (failreason)
+ {
+ case MAXIMUM_SIZE_EXCEEDED: RenameOnError(MaximumSizeExceeded); break;
+ case HASHSUM_MISMATCH: RenameOnError(HashSumMismatch); break;
+ case OTHER: break;
+ }
- // report mirror failure back to LP if we actually use a mirror
if (FailReason.empty() == false)
- ReportMirrorFailure(FailReason);
+ ReportMirrorFailureToCentral(*this, FailReason, ErrorText);
else
- ReportMirrorFailure(ErrorText);
+ ReportMirrorFailureToCentral(*this, ErrorText, ErrorText);
if (QueueCounter > 1)
Status = StatIdle;
{
case HashSumMismatch:
errtext = _("Hash Sum mismatch");
- Status = StatAuthError;
- ReportMirrorFailure("HashChecksumFailure");
break;
case SizeMismatch:
errtext = _("Size mismatch");
Status = StatAuthError;
- ReportMirrorFailure("SizeFailure");
break;
case InvalidFormat:
errtext = _("Invalid file format");
break;
case MaximumSizeExceeded:
// the method is expected to report a good error for this
- Status = StatError;
break;
case PDiffError:
// no handling here, done by callers
}
/*}}}*/
// Acquire::Item::ReportMirrorFailure /*{{{*/
-void pkgAcquire::Item::ReportMirrorFailure(string const &FailCode)
+void pkgAcquire::Item::ReportMirrorFailure(std::string const &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
- string report = _config->Find("Methods::Mirror::ProblemReporting",
- "/usr/lib/apt/apt-report-mirror-failure");
- if(!FileExists(report))
- return;
-
- std::vector<char const*> Args;
- Args.push_back(report.c_str());
- Args.push_back(UsedMirror.c_str());
- Args.push_back(DescURI().c_str());
- Args.push_back(FailCode.c_str());
- Args.push_back(NULL);
-
- pid_t pid = ExecFork();
- if(pid < 0)
- {
- _error->Error("ReportMirrorFailure Fork failed");
- return;
- }
- else if(pid == 0)
- {
- execvp(Args[0], (char**)Args.data());
- 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());
- }
+ ReportMirrorFailureToCentral(*this, FailCode, FailCode);
}
/*}}}*/
std::string pkgAcquire::Item::HashSum() const /*{{{*/
}
/*}}}*/
// AcqMetaBase::GenerateAuthWarning - Check gpg authentication error /*{{{*/
+/* This method is called from ::Failed handlers. If it returns true,
+ no fallback to other files or modi is performed */
bool pkgAcqMetaBase::CheckStopAuthentication(pkgAcquire::Item * const I, const std::string &Message)
{
- // FIXME: this entire function can do now that we disallow going to
- // a unauthenticated state and can cleanly rollback
-
string const Final = I->GetFinalFilename();
- if(FileExists(Final))
+ std::string const GPGError = LookupTag(Message, "Message");
+ if (FileExists(Final))
{
I->Status = StatTransientNetworkError;
- _error->Warning(_("An error occurred during the signature "
- "verification. The repository is not updated "
- "and the previous index files will be used. "
- "GPG error: %s: %s"),
- Desc.Description.c_str(),
- LookupTag(Message,"Message").c_str());
+ _error->Warning(_("An error occurred during the signature verification. "
+ "The repository is not updated and the previous index files will be used. "
+ "GPG error: %s: %s"),
+ Desc.Description.c_str(),
+ GPGError.c_str());
RunScripts("APT::Update::Auth-Failure");
return true;
} else if (LookupTag(Message,"Message").find("NODATA") != string::npos) {
/* Invalid signature file, reject (LP: #346386) (Closes: #627642) */
_error->Error(_("GPG error: %s: %s"),
- Desc.Description.c_str(),
- LookupTag(Message,"Message").c_str());
+ Desc.Description.c_str(),
+ GPGError.c_str());
I->Status = StatAuthError;
return true;
} else {
_error->Warning(_("GPG error: %s: %s"),
- Desc.Description.c_str(),
- LookupTag(Message,"Message").c_str());
+ Desc.Description.c_str(),
+ GPGError.c_str());
}
// gpgv method failed
- ReportMirrorFailure("GPGFailure");
+ ReportMirrorFailureToCentral(*this, "GPGFailure", GPGError);
return false;
}
/*}}}*/
// We have just finished downloading a Release file (it is not
// verified yet)
+ // Save the final base URI we got this Release file from
+ if (I->UsedMirror.empty() == false && _config->FindB("Acquire::SameMirrorForAllIndexes", true))
+ {
+ if (APT::String::Endswith(I->Desc.URI, "InRelease"))
+ TransactionManager->BaseURI = I->Desc.URI.substr(0, I->Desc.URI.length() - strlen("InRelease"));
+ else
+ TransactionManager->BaseURI = I->Desc.URI.substr(0, I->Desc.URI.length() - strlen("Release"));
+ }
+
std::string const FileName = LookupTag(Message,"Filename");
if (FileName != I->DestFile && RealFileExists(I->DestFile) == false)
{
}
}
/*}}}*/
-bool pkgAcqMetaBase::VerifyVendor(string const &Message) /*{{{*/
+bool pkgAcqMetaBase::VerifyVendor(string const &) /*{{{*/
{
- string::size_type pos;
-
- // check for missing sigs (that where not fatal because otherwise we had
- // bombed earlier)
- string missingkeys;
- string msg = _("There is no public key available for the "
- "following key IDs:\n");
- pos = Message.find("NO_PUBKEY ");
- if (pos != std::string::npos)
- {
- string::size_type start = pos+strlen("NO_PUBKEY ");
- string Fingerprint = Message.substr(start, Message.find("\n")-start);
- missingkeys += (Fingerprint);
- }
- if(!missingkeys.empty())
- _error->Warning("%s", (msg + missingkeys).c_str());
-
string Transformed = TransactionManager->MetaIndexParser->GetExpectedDist();
if (Transformed == "../project/experimental")
Transformed = "experimental";
}
- pos = Transformed.rfind('/');
+ auto pos = Transformed.rfind('/');
if (pos != string::npos)
{
Transformed = Transformed.substr(0, pos);
IndexTarget const &Target)
: pkgAcqTransactionItem(Owner, TransactionManager, Target), d(NULL)
{
+}
+ /*}}}*/
+void pkgAcqBaseIndex::Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf)/*{{{*/
+{
+ pkgAcquire::Item::Failed(Message, Cnf);
+ if (TransactionManager == nullptr || TransactionManager->MetaIndexParser == nullptr ||
+ Status != StatAuthError)
+ return;
+
+ ErrorText.append("Release file created at: ");
+ auto const timespec = TransactionManager->MetaIndexParser->GetDate();
+ if (timespec == 0)
+ ErrorText.append("<unknown>");
+ else
+ ErrorText.append(TimeRFC1123(timespec));
+ ErrorText.append("\n");
}
/*}}}*/
pkgAcqBaseIndex::~pkgAcqBaseIndex() {}
/*}}}*/
void pkgAcqDiffIndex::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf)/*{{{*/
{
- Item::Failed(Message,Cnf);
+ pkgAcqBaseIndex::Failed(Message,Cnf);
Status = StatDone;
if(Debug)
/*}}}*/
void pkgAcqIndexDiffs::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf)/*{{{*/
{
- Item::Failed(Message,Cnf);
+ pkgAcqBaseIndex::Failed(Message,Cnf);
Status = StatDone;
DestFile = GetKeepCompressedFileName(GetPartialFileNameFromURI(Target.URI), Target);
if(Debug)
std::clog << "pkgAcqIndexMergeDiffs failed: " << Desc.URI << " with " << Message << std::endl;
- Item::Failed(Message,Cnf);
+ pkgAcqBaseIndex::Failed(Message,Cnf);
Status = StatDone;
// check if we are the first to fail, otherwise we are done here
// AcqIndex::Failed - getting the indexfile failed /*{{{*/
void pkgAcqIndex::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf)
{
- Item::Failed(Message,Cnf);
+ pkgAcqBaseIndex::Failed(Message,Cnf);
// authorisation matches will not be fixed by other compression types
if (Status != StatAuthError)