#include <ctime>
#include <sstream>
#include <numeric>
+#include <random>
#include <apti18n.h>
/*}}}*/
if (TargetIsAllowedToBe(TransactionManager->Target, msg) == true)
{
- MessageInsecureRepository(false, msgstr, repo);
+ //MessageInsecureRepository(false, msgstr, repo);
return true;
}
// ---------------------------------------------------------------------
/* We return to an idle state if there are still other queues that could
fetch this object */
+static void formatHashsum(std::ostream &out, HashString const &hs)
+{
+ auto const type = hs.HashType();
+ if (type == "Checksum-FileSize")
+ out << " - Filesize";
+ else
+ out << " - " << type;
+ out << ':' << hs.HashValue();
+ if (hs.usable() == false)
+ out << " [weak]";
+ out << std::endl;
+}
void pkgAcquire::Item::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf)
{
if (QueueCounter <= 1)
{
out << "Hashes of expected file:" << std::endl;
for (auto const &hs: ExpectedHashes)
- {
- out << " - " << hs.toStr();
- if (hs.usable() == false)
- out << " [weak]";
- out << std::endl;
- }
+ formatHashsum(out, hs);
}
if (failreason == HASHSUM_MISMATCH)
{
std::string const tagname = std::string(*type) + "-Hash";
std::string const hashsum = LookupTag(Message, tagname.c_str());
if (hashsum.empty() == false)
- {
- auto const hs = HashString(*type, hashsum);
- out << " - " << hs.toStr();
- if (hs.usable() == false)
- out << " [weak]";
- out << std::endl;
- }
+ formatHashsum(out, HashString(*type, hashsum));
}
- out << "Last modification reported: " << LookupTag(Message, "Last-Modified", "<none>") << std::endl;
}
+ auto const lastmod = LookupTag(Message, "Last-Modified", "");
+ if (lastmod.empty() == false)
+ out << "Last modification reported: " << lastmod << std::endl;
}
ErrorText = out.str();
}
return false;
}
/*}}}*/
+int pkgAcquire::Item::Priority() /*{{{*/
+{
+ // Stage 1: Meta indices and diff indices
+ // - those need to be fetched first to have progress reporting working
+ // for the rest
+ if (dynamic_cast<pkgAcqMetaSig*>(this) != nullptr
+ || dynamic_cast<pkgAcqMetaBase*>(this) != nullptr
+ || dynamic_cast<pkgAcqDiffIndex*>(this) != nullptr)
+ return 1000;
+ // Stage 2: Diff files
+ // - fetch before complete indexes so we can apply the diffs while fetching
+ // larger files.
+ if (dynamic_cast<pkgAcqIndexDiffs*>(this) != nullptr ||
+ dynamic_cast<pkgAcqIndexMergeDiffs*>(this) != nullptr)
+ return 800;
+
+ // Stage 3: The rest - complete index files and other stuff
+ return 500;
+}
+ /*}}}*/
pkgAcqTransactionItem::pkgAcqTransactionItem(pkgAcquire * const Owner, /*{{{*/
pkgAcqMetaClearSig * const transactionManager, IndexTarget const &target) :
if (hasReleaseFile && verify == false)
hasHashes = std::any_of(IndexTargets.begin(), IndexTargets.end(),
[&](IndexTarget const &Target) { return TransactionManager->MetaIndexParser->Exists(Target.MetaKey); });
+ if (_config->FindB("Acquire::IndexTargets::Randomized", true) && likely(IndexTargets.empty() == false))
+ {
+ /* For fallback handling and to have some reasonable progress information
+ we can't randomize everything, but at least the order in the same type
+ can be as we shouldn't be telling the mirrors (and everyone else watching)
+ which is native/foreign arch, specific order of preference of translations, … */
+ auto range_start = IndexTargets.begin();
+ std::random_device rd;
+ std::default_random_engine g(rd());
+ do {
+ auto const type = range_start->Option(IndexTarget::CREATED_BY);
+ auto const range_end = std::find_if_not(range_start, IndexTargets.end(),
+ [&type](IndexTarget const &T) { return type == T.Option(IndexTarget::CREATED_BY); });
+ std::shuffle(range_start, range_end, g);
+ range_start = range_end;
+ } while (range_start != IndexTargets.end());
+ }
for (auto&& Target: IndexTargets)
{
// if we have seen a target which is created-by a target this one here is declared a
/*}}}*/
bool pkgAcqMetaBase::VerifyVendor(string const &) /*{{{*/
{
- string Transformed = TransactionManager->MetaIndexParser->GetExpectedDist();
-
- if (Transformed == "../project/experimental")
- {
- Transformed = "experimental";
- }
-
- auto pos = Transformed.rfind('/');
- if (pos != string::npos)
- {
- Transformed = Transformed.substr(0, pos);
- }
-
- if (Transformed == ".")
- {
- Transformed = "";
- }
-
if (TransactionManager->MetaIndexParser->GetValidUntil() > 0)
{
time_t const invalid_since = time(NULL) - TransactionManager->MetaIndexParser->GetValidUntil();
TransactionManager->LastMetaIndexParser = NULL;
}
- if (_config->FindB("Debug::pkgAcquire::Auth", false))
+ if (_config->FindB("Debug::pkgAcquire::Auth", false))
{
std::cerr << "Got Codename: " << TransactionManager->MetaIndexParser->GetCodename() << std::endl;
+ std::cerr << "Got Suite: " << TransactionManager->MetaIndexParser->GetSuite() << std::endl;
std::cerr << "Expecting Dist: " << TransactionManager->MetaIndexParser->GetExpectedDist() << std::endl;
- std::cerr << "Transformed Dist: " << Transformed << std::endl;
}
- if (TransactionManager->MetaIndexParser->CheckDist(Transformed) == false)
+ // One day that might become fatal…
+ auto const ExpectedDist = TransactionManager->MetaIndexParser->GetExpectedDist();
+ auto const NowCodename = TransactionManager->MetaIndexParser->GetCodename();
+ if (TransactionManager->MetaIndexParser->CheckDist(ExpectedDist) == false)
+ _error->Warning(_("Conflicting distribution: %s (expected %s but got %s)"),
+ Desc.Description.c_str(), ExpectedDist.c_str(), NowCodename.c_str());
+ // might be okay, might be not
+ if (TransactionManager->LastMetaIndexParser != nullptr)
{
- // This might become fatal one day
-// Status = StatAuthError;
-// ErrorText = "Conflicting distribution; expected "
-// + MetaIndexParser->GetExpectedDist() + " but got "
-// + MetaIndexParser->GetCodename();
-// return false;
- if (!Transformed.empty())
- {
- _error->Warning(_("Conflicting distribution: %s (expected %s but got %s)"),
- Desc.Description.c_str(),
- Transformed.c_str(),
- TransactionManager->MetaIndexParser->GetCodename().c_str());
- }
+ auto const LastCodename = TransactionManager->LastMetaIndexParser->GetCodename();
+ if (LastCodename.empty() == false && NowCodename.empty() == false && LastCodename != NowCodename)
+ _error->Warning(_("Conflicting distribution: %s (expected %s but got %s)"),
+ Desc.Description.c_str(), LastCodename.c_str(), NowCodename.c_str());
}
-
return true;
}
/*}}}*/
}
else if(MetaIndex->CheckAuthDone(Message) == true)
{
- if (TransactionManager->IMSHit == false)
+ auto const Releasegpg = GetFinalFilename();
+ auto const Release = MetaIndex->GetFinalFilename();
+ // if this is an IMS-Hit on Release ensure we also have the the Release.gpg file stored
+ // (previously an unknown pubkey) – but only if the Release file exists locally (unlikely
+ // event of InRelease removed from the mirror causing fallback but still an IMS-Hit)
+ if (TransactionManager->IMSHit == false ||
+ (FileExists(Releasegpg) == false && FileExists(Release) == true))
{
- TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename());
- TransactionManager->TransactionStageCopy(MetaIndex, MetaIndex->DestFile, MetaIndex->GetFinalFilename());
+ TransactionManager->TransactionStageCopy(this, DestFile, Releasegpg);
+ TransactionManager->TransactionStageCopy(MetaIndex, MetaIndex->DestFile, Release);
}
}
else if (MetaIndex->Status != StatAuthError)
{
// 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, TransactionManager, Target);
+ new pkgAcqIndexDiffs(Owner, TransactionManager, Target, UsedMirror, Target.URI);
}
/*}}}*/
static bool RemoveFileForBootstrapLinking(bool const Debug, std::string const &For, std::string const &Boot)/*{{{*/
}
}
+ std::string indexURI = Desc.URI;
+ auto const byhashidx = indexURI.find("/by-hash/");
+ if (byhashidx != std::string::npos)
+ indexURI = indexURI.substr(0, byhashidx - strlen(".diff"));
+ else
+ {
+ auto end = indexURI.length() - strlen(".diff/Index");
+ if (CurrentCompressionExtension != "uncompressed")
+ end -= (1 + CurrentCompressionExtension.length());
+ indexURI = indexURI.substr(0, end);
+ }
+
if (pdiff_merge == false)
- new pkgAcqIndexDiffs(Owner, TransactionManager, Target, available_patches);
+ new pkgAcqIndexDiffs(Owner, TransactionManager, Target, UsedMirror, indexURI, available_patches);
else
{
diffs = new std::vector<pkgAcqIndexMergeDiffs*>(available_patches.size());
for(size_t i = 0; i < available_patches.size(); ++i)
(*diffs)[i] = new pkgAcqIndexMergeDiffs(Owner, TransactionManager,
- Target,
+ Target, UsedMirror, indexURI,
available_patches[i],
diffs);
}
pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire * const Owner,
pkgAcqMetaClearSig * const TransactionManager,
IndexTarget const &Target,
+ std::string const &indexUsedMirror, std::string const &indexURI,
vector<DiffInfo> const &diffs)
- : pkgAcqBaseIndex(Owner, TransactionManager, Target), d(NULL),
+ : pkgAcqBaseIndex(Owner, TransactionManager, Target), indexURI(indexURI),
available_patches(diffs)
{
DestFile = GetKeepCompressedFileName(GetPartialFileNameFromURI(Target.URI), Target);
Description = Target.Description;
Desc.ShortDesc = Target.ShortDesc;
+ UsedMirror = indexUsedMirror;
+ if (UsedMirror == "DIRECT")
+ UsedMirror.clear();
+ else if (UsedMirror.empty() == false && Description.find(" ") != string::npos)
+ Description.replace(0, Description.find(" "), UsedMirror);
+
if(available_patches.empty() == true)
{
// we are done (yeah!), check hashes against the final file
}
// queue the right diff
- Desc.URI = Target.URI + ".diff/" + available_patches[0].file + ".gz";
+ Desc.URI = indexURI + ".diff/" + available_patches[0].file + ".gz";
Desc.Description = Description + " " + available_patches[0].file + string(".pdiff");
DestFile = GetKeepCompressedFileName(GetPartialFileNameFromURI(Target.URI + ".diff/" + available_patches[0].file), Target);
// see if there is more to download
if(available_patches.empty() == false)
{
- new pkgAcqIndexDiffs(Owner, TransactionManager, Target, available_patches);
+ new pkgAcqIndexDiffs(Owner, TransactionManager, Target, UsedMirror, indexURI, available_patches);
Finish();
} else {
DestFile = PatchedFile;
pkgAcqIndexMergeDiffs::pkgAcqIndexMergeDiffs(pkgAcquire * const Owner,
pkgAcqMetaClearSig * const TransactionManager,
IndexTarget const &Target,
+ std::string const &indexUsedMirror, std::string const &indexURI,
DiffInfo const &patch,
std::vector<pkgAcqIndexMergeDiffs*> const * const allPatches)
- : pkgAcqBaseIndex(Owner, TransactionManager, Target), d(NULL),
- patch(patch), allPatches(allPatches), State(StateFetchDiff)
+ : pkgAcqBaseIndex(Owner, TransactionManager, Target), indexURI(indexURI),
+ patch(patch), allPatches(allPatches), State(StateFetchDiff)
{
Debug = _config->FindB("Debug::pkgAcquire::Diffs",false);
- Desc.Owner = this;
Description = Target.Description;
+ UsedMirror = indexUsedMirror;
+ if (UsedMirror == "DIRECT")
+ UsedMirror.clear();
+ else if (UsedMirror.empty() == false && Description.find(" ") != string::npos)
+ Description.replace(0, Description.find(" "), UsedMirror);
+
+ Desc.Owner = this;
Desc.ShortDesc = Target.ShortDesc;
- Desc.URI = Target.URI + ".diff/" + patch.file + ".gz";
+ Desc.URI = indexURI + ".diff/" + patch.file + ".gz";
Desc.Description = Description + " " + patch.file + ".pdiff";
- DestFile = GetPartialFileNameFromURI(Desc.URI);
+ DestFile = GetPartialFileNameFromURI(Target.URI + ".diff/" + patch.file + ".gz");
if(Debug)
std::clog << "pkgAcqIndexMergeDiffs: " << Desc.URI << std::endl;
{
// copy FinalFile into partial/ so that we check the hash again
string const FinalFile = GetExistingFilename(GetFinalFileNameFromURI(Target.URI));
+ DestFile = GetKeepCompressedFileName(GetPartialFileNameFromURI(Target.URI), Target);
if (symlink(FinalFile.c_str(), DestFile.c_str()) != 0)
_error->WarningE("pkgAcqIndex::StageDownloadDone", "Symlinking final file %s back to %s failed", FinalFile.c_str(), DestFile.c_str());
else
Filename = DestFile;
}
Stage = STAGE_DECOMPRESS_AND_VERIFY;
- Desc.URI = "store:" + Filename;
+ if (Filename != DestFile && flExtension(Filename) == flExtension(DestFile))
+ Desc.URI = "copy:" + Filename;
+ else
+ Desc.URI = "store:" + Filename;
QueueURI(Desc);
SetActiveSubprocess(::URI(Desc.URI).Access);
return;
// Create the item
Local = false;
- QueueURI(Desc);
-
++Vf;
+ QueueURI(Desc);
return true;
}
return false;
TemporaryDirectory = tmpname;
ChangeOwnerAndPermissionOfFile("Item::QueueURI", TemporaryDirectory.c_str(),
- SandboxUser.c_str(), "root", 0700);
+ SandboxUser.c_str(), ROOT_GROUP, 0700);
DestFile = flCombine(TemporaryDirectory, DestFileName);
if (DestDir.empty() == false)
pkgCache::PkgIterator const Pkg = Ver.ParentPkg();
if (Pkg->CurrentVer != 0 && Pkg.CurrentVer() == Ver)
{
- std::string const basename = std::string("/usr/share/doc/") + Pkg.Name() + "/changelog";
+ std::string const root = _config->FindDir("Dir");
+ std::string const basename = root + std::string("usr/share/doc/") + Pkg.Name() + "/changelog";
std::string const debianname = basename + ".Debian";
if (FileExists(debianname))
return "copy://" + debianname;
should be so this could produce request order-dependent anomalies */
if (OpenMaybeClearSignedFile(Rls.FileName(), rf) == true)
{
- pkgTagFile TagFile(&rf, rf.Size());
+ pkgTagFile TagFile(&rf);
pkgTagSection Section;
if (TagFile.Step(Section) == true)
server = Section.FindS("Changelogs");