#include <apt-pkg/error.h>
#include <apt-pkg/strutl.h>
#include <apt-pkg/fileutl.h>
-#include <apt-pkg/sha1.h>
#include <apt-pkg/tagfile.h>
-#include <apt-pkg/indexrecords.h>
+#include <apt-pkg/metaindex.h>
#include <apt-pkg/acquire.h>
#include <apt-pkg/hashes.h>
#include <apt-pkg/indexfile.h>
#include <apt-pkg/pkgcache.h>
#include <apt-pkg/cacheiterators.h>
#include <apt-pkg/pkgrecords.h>
+#include <apt-pkg/gpgv.h>
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string>
-#include <sstream>
#include <stdio.h>
#include <ctime>
+#include <sstream>
#include <apti18n.h>
/*}}}*/
return _config->FindDir("Dir::State::lists") + URItoFileName(uri);
}
/*}}}*/
-static std::string GetCompressedFileName(std::string const &URI, std::string const &Name, std::string const &Ext) /*{{{*/
+static std::string GetCompressedFileName(IndexTarget const &Target, std::string const &Name, std::string const &Ext) /*{{{*/
{
if (Ext.empty() || Ext == "uncompressed")
return Name;
// do not reverify cdrom sources as apt-cdrom may rewrite the Packages
// file when its doing the indexcopy
- if (URI.substr(0,6) == "cdrom:")
+ if (Target.URI.substr(0,6) == "cdrom:")
return Name;
// adjust DestFile if its compressed on disk
- if (_config->FindB("Acquire::GzipIndexes",false) == true)
+ if (Target.KeepCompressed == true)
return Name + '.' + Ext;
return Name;
}
}
/*}}}*/
-static bool AllowInsecureRepositories(indexRecords const * const MetaIndexParser, pkgAcqMetaBase * const TransactionManager, pkgAcquire::Item * const I) /*{{{*/
+static bool AllowInsecureRepositories(metaIndex const * const MetaIndexParser, pkgAcqMetaClearSig * const TransactionManager, pkgAcquire::Item * const I) /*{{{*/
{
- if(MetaIndexParser->IsAlwaysTrusted() || _config->FindB("Acquire::AllowInsecureRepositories") == true)
+ if(MetaIndexParser->GetTrusted() == metaIndex::TRI_YES || _config->FindB("Acquire::AllowInsecureRepositories") == true)
return true;
_error->Error(_("Use --allow-insecure-repositories to force the update"));
return false;
}
/*}}}*/
-static HashStringList GetExpectedHashesFromFor(indexRecords * const Parser, std::string const MetaKey)/*{{{*/
+static HashStringList GetExpectedHashesFromFor(metaIndex * const Parser, std::string const &MetaKey)/*{{{*/
{
if (Parser == NULL)
return HashStringList();
- indexRecords::checkSum * const R = Parser->Lookup(MetaKey);
+ metaIndex::checkSum * const R = Parser->Lookup(MetaKey);
if (R == NULL)
return HashStringList();
return R->Hashes;
we can at least trust them for integrity of the download itself.
Only repositories without a Release file can (obviously) not have
hashes – and they are very uncommon and strongly discouraged */
- return TransactionManager->MetaIndexParser != NULL;
+ return TransactionManager->MetaIndexParser != NULL &&
+ TransactionManager->MetaIndexParser->GetLoadedSuccessfully() != metaIndex::TRI_UNSET;
}
HashStringList pkgAcqTransactionItem::GetExpectedHashes() const
{
if (State == StateFetchDiff)
return patch.download_hashes;
else if (State == StateApplyDiff)
- return GetExpectedHashesFor(Target->MetaKey);
+ return GetExpectedHashesFor(Target.MetaKey);
return HashStringList();
}
}
std::string pkgAcqIndex::GetFinalFilename() const
{
- std::string const FinalFile = GetFinalFileNameFromURI(Target->URI);
- return GetCompressedFileName(Target->URI, FinalFile, CurrentCompressionExtension);
+ std::string const FinalFile = GetFinalFileNameFromURI(Target.URI);
+ return GetCompressedFileName(Target, FinalFile, CurrentCompressionExtension);
}
std::string pkgAcqMetaSig::GetFinalFilename() const
{
- return GetFinalFileNameFromURI(Target->URI);
+ return GetFinalFileNameFromURI(Target.URI);
}
std::string pkgAcqBaseIndex::GetFinalFilename() const
{
- return GetFinalFileNameFromURI(Target->URI);
+ return GetFinalFileNameFromURI(Target.URI);
}
std::string pkgAcqMetaBase::GetFinalFilename() const
{
- return GetFinalFileNameFromURI(DataTarget.URI);
+ return GetFinalFileNameFromURI(Target.URI);
}
std::string pkgAcqArchive::GetFinalFilename() const
{
// pkgAcqTransactionItem::GetMetaKey and specialisations for child classes /*{{{*/
std::string pkgAcqTransactionItem::GetMetaKey() const
{
- return Target->MetaKey;
+ return Target.MetaKey;
}
std::string pkgAcqIndex::GetMetaKey() const
{
if (Stage == STAGE_DECOMPRESS_AND_VERIFY || CurrentCompressionExtension == "uncompressed")
- return Target->MetaKey;
- return Target->MetaKey + "." + CurrentCompressionExtension;
+ return Target.MetaKey;
+ return Target.MetaKey + "." + CurrentCompressionExtension;
}
std::string pkgAcqDiffIndex::GetMetaKey() const
{
- return Target->MetaKey + ".diff/Index";
+ return Target.MetaKey + ".diff/Index";
}
/*}}}*/
//pkgAcqTransactionItem::TransactionState and specialisations for child classes /*{{{*/
case TransactionCommit:
break;
case TransactionAbort:
- std::string const Partial = GetPartialFileNameFromURI(Target->URI);
+ std::string const Partial = GetPartialFileNameFromURI(Target.URI);
unlink(Partial.c_str());
break;
}
}
/*}}}*/
-// IndexTarget - Constructor /*{{{*/
-IndexTarget::IndexTarget(std::string const &MetaKey, std::string const &ShortDesc,
- std::string const &LongDesc, std::string const &URI, bool const IsOptional,
- std::map<std::string, std::string> const &Options) :
- URI(URI), Description(LongDesc), ShortDesc(ShortDesc), MetaKey(MetaKey), IsOptional(IsOptional), Options(Options)
-{
-}
- /*}}}*/
-
class APT_HIDDEN NoActionItem : public pkgAcquire::Item /*{{{*/
/* The sole purpose of this class is having an item which does nothing to
reach its done state to prevent cleanup deleting the mentioned file.
Handy in cases in which we know we have the file already, like IMS-Hits. */
{
- IndexTarget const * const Target;
+ IndexTarget const Target;
public:
- virtual std::string DescURI() const {return Target->URI;};
- virtual HashStringList GetExpectedHashes() const {return HashStringList();};
+ virtual std::string DescURI() const APT_OVERRIDE {return Target.URI;};
+ virtual HashStringList GetExpectedHashes() const APT_OVERRIDE {return HashStringList();};
- NoActionItem(pkgAcquire * const Owner, IndexTarget const * const Target) :
+ NoActionItem(pkgAcquire * const Owner, IndexTarget const &Target) :
pkgAcquire::Item(Owner), Target(Target)
{
Status = StatDone;
- DestFile = GetFinalFileNameFromURI(Target->URI);
+ DestFile = GetFinalFileNameFromURI(Target.URI);
}
};
/*}}}*/
// Acquire::Item::Item - Constructor /*{{{*/
APT_IGNORE_DEPRECATED_PUSH
-pkgAcquire::Item::Item(pkgAcquire * const Owner) :
- FileSize(0), PartialSize(0), Mode(0), Complete(false), Local(false),
- QueueCounter(0), ExpectedAdditionalItems(0), Owner(Owner)
+pkgAcquire::Item::Item(pkgAcquire * const owner) :
+ FileSize(0), PartialSize(0), Mode(0), ID(0), Complete(false), Local(false),
+ QueueCounter(0), ExpectedAdditionalItems(0), Owner(owner), d(NULL)
{
Owner->Add(this);
Status = StatIdle;
return Owner;
}
/*}}}*/
+APT_CONST pkgAcquire::ItemDesc &pkgAcquire::Item::GetItemDesc() /*{{{*/
+{
+ return Desc;
+}
+ /*}}}*/
APT_CONST bool pkgAcquire::Item::IsTrusted() const /*{{{*/
{
return false;
{
if(ErrorText.empty())
ErrorText = LookupTag(Message,"Message");
- UsedMirror = LookupTag(Message,"UsedMirror");
if (QueueCounter <= 1)
{
/* This indicates that the file is not available right now but might
FileSize = Size;
}
/*}}}*/
+// Acquire::Item::VerifyDone - check if Item was downloaded OK /*{{{*/
+/* Note that hash-verification is 'hardcoded' in acquire-worker and has
+ * already passed if this method is called. */
+bool pkgAcquire::Item::VerifyDone(std::string const &Message,
+ pkgAcquire::MethodConfig const * const /*Cnf*/)
+{
+ std::string const FileName = LookupTag(Message,"Filename");
+ if (FileName.empty() == true)
+ {
+ Status = StatError;
+ ErrorText = "Method gave a blank filename";
+ return false;
+ }
+
+ return true;
+}
+ /*}}}*/
// Acquire::Item::Done - Item downloaded OK /*{{{*/
-void pkgAcquire::Item::Done(string const &Message, HashStringList const &Hashes,
+void pkgAcquire::Item::Done(string const &/*Message*/, HashStringList const &Hashes,
pkgAcquire::MethodConfig const * const /*Cnf*/)
{
// We just downloaded something..
- string FileName = LookupTag(Message,"Filename");
- UsedMirror = LookupTag(Message,"UsedMirror");
- unsigned long long const downloadedSize = Hashes.FileSize();
- if (downloadedSize != 0)
+ if (FileSize == 0)
{
- if (Complete == false && !Local && FileName == DestFile)
+ unsigned long long const downloadedSize = Hashes.FileSize();
+ if (downloadedSize != 0)
{
- if (Owner->Log != 0)
- Owner->Log->Fetched(Hashes.FileSize(),atoi(LookupTag(Message,"Resume-Point","0").c_str()));
+ FileSize = downloadedSize;
}
-
- if (FileSize == 0)
- FileSize= downloadedSize;
}
Status = StatDone;
ErrorText = string();
Status = StatError;
break;
case NotClearsigned:
- errtext = _("Does not start with a cleartext signature");
- Status = StatError;
+ strprintf(errtext, _("Clearsigned file isn't valid, got '%s' (does the network require authentication?)"), "NOSPLIT");
+ Status = StatAuthError;
break;
case MaximumSizeExceeded:
// the method is expected to report a good error for this
/*}}}*/
pkgAcqTransactionItem::pkgAcqTransactionItem(pkgAcquire * const Owner, /*{{{*/
- pkgAcqMetaBase * const TransactionManager, IndexTarget const * const Target) :
- pkgAcquire::Item(Owner), Target(Target), TransactionManager(TransactionManager)
+ pkgAcqMetaClearSig * const transactionManager, IndexTarget const &target) :
+ pkgAcquire::Item(Owner), d(NULL), Target(target), TransactionManager(transactionManager)
{
if (TransactionManager != this)
TransactionManager->Add(this);
{
}
/*}}}*/
-HashStringList pkgAcqTransactionItem::GetExpectedHashesFor(std::string const MetaKey) const /*{{{*/
+HashStringList pkgAcqTransactionItem::GetExpectedHashesFor(std::string const &MetaKey) const /*{{{*/
{
return GetExpectedHashesFromFor(TransactionManager->MetaIndexParser, MetaKey);
}
// AcqMetaBase - Constructor /*{{{*/
pkgAcqMetaBase::pkgAcqMetaBase(pkgAcquire * const Owner,
- pkgAcqMetaBase * const TransactionManager,
- std::vector<IndexTarget*> const * const IndexTargets,
- IndexTarget const &DataTarget,
- indexRecords * const MetaIndexParser)
-: pkgAcqTransactionItem(Owner, TransactionManager, NULL), DataTarget(DataTarget),
- MetaIndexParser(MetaIndexParser), LastMetaIndexParser(NULL), IndexTargets(IndexTargets),
+ pkgAcqMetaClearSig * const TransactionManager,
+ std::vector<IndexTarget> const &IndexTargets,
+ IndexTarget const &DataTarget)
+: pkgAcqTransactionItem(Owner, TransactionManager, DataTarget), d(NULL),
+ IndexTargets(IndexTargets),
AuthPass(false), IMSHit(false)
{
}
_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\n"),
+ "GPG error: %s: %s"),
Desc.Description.c_str(),
LookupTag(Message,"Message").c_str());
RunScripts("APT::Update::Auth-Failure");
_error->Error(_("GPG error: %s: %s"),
Desc.Description.c_str(),
LookupTag(Message,"Message").c_str());
- I->Status = StatError;
+ I->Status = StatAuthError;
return true;
} else {
_error->Warning(_("GPG error: %s: %s"),
Header += MaximumSize;
string const FinalFile = GetFinalFilename();
-
struct stat Buf;
if (stat(FinalFile.c_str(),&Buf) == 0)
Header += "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
// We have just finished downloading a Release file (it is not
// verified yet)
- string const FileName = LookupTag(Message,"Filename");
- if (FileName.empty() == true)
- {
- I->Status = StatError;
- I->ErrorText = "Method gave a blank filename";
- return false;
- }
-
- if (FileName != I->DestFile)
+ std::string const FileName = LookupTag(Message,"Filename");
+ if (FileName != I->DestFile && RealFileExists(I->DestFile) == false)
{
I->Local = true;
I->Desc.URI = "copy:" + FileName;
}
if (RealFileExists(FinalInRelease) || RealFileExists(FinalRelease))
{
- TransactionManager->LastMetaIndexParser = new indexRecords;
- _error->PushToStack();
- if (RealFileExists(FinalInRelease))
- TransactionManager->LastMetaIndexParser->Load(FinalInRelease);
- else
- TransactionManager->LastMetaIndexParser->Load(FinalRelease);
- // its unlikely to happen, but if what we have is bad ignore it
- if (_error->PendingError())
+ TransactionManager->LastMetaIndexParser = TransactionManager->MetaIndexParser->UnloadedClone();
+ if (TransactionManager->LastMetaIndexParser != NULL)
{
- delete TransactionManager->LastMetaIndexParser;
- TransactionManager->LastMetaIndexParser = NULL;
+ _error->PushToStack();
+ if (RealFileExists(FinalInRelease))
+ TransactionManager->LastMetaIndexParser->Load(FinalInRelease, NULL);
+ else
+ TransactionManager->LastMetaIndexParser->Load(FinalRelease, NULL);
+ // its unlikely to happen, but if what we have is bad ignore it
+ if (_error->PendingError())
+ {
+ delete TransactionManager->LastMetaIndexParser;
+ TransactionManager->LastMetaIndexParser = NULL;
+ }
+ _error->RevertToStack();
}
- _error->RevertToStack();
}
}
- if (TransactionManager->MetaIndexParser->Load(DestFile) == false)
+ if (TransactionManager->MetaIndexParser->Load(DestFile, &ErrorText) == false)
{
Status = StatAuthError;
- ErrorText = TransactionManager->MetaIndexParser->ErrorText;
return false;
}
// at this point the real Items are loaded in the fetcher
ExpectedAdditionalItems = 0;
- vector <IndexTarget*>::const_iterator Target;
- for (Target = IndexTargets->begin();
- Target != IndexTargets->end();
+ for (std::vector <IndexTarget>::const_iterator Target = IndexTargets.begin();
+ Target != IndexTargets.end();
++Target)
{
bool trypdiff = _config->FindB("Acquire::PDiffs", true);
if (verify == true)
{
- if (TransactionManager->MetaIndexParser->Exists((*Target)->MetaKey) == false)
+ if (TransactionManager->MetaIndexParser->Exists(Target->MetaKey) == false)
{
// optional targets that we do not have in the Release file are skipped
- if ((*Target)->IsOptional)
+ if (Target->IsOptional)
continue;
Status = StatAuthError;
- strprintf(ErrorText, _("Unable to find expected entry '%s' in Release file (Wrong sources.list entry or malformed file)"), (*Target)->MetaKey.c_str());
+ strprintf(ErrorText, _("Unable to find expected entry '%s' in Release file (Wrong sources.list entry or malformed file)"), Target->MetaKey.c_str());
return;
}
- if (RealFileExists(GetFinalFileNameFromURI((*Target)->URI)))
+ if (RealFileExists(GetFinalFileNameFromURI(Target->URI)))
{
if (TransactionManager->LastMetaIndexParser != NULL)
{
- HashStringList const newFile = GetExpectedHashesFromFor(TransactionManager->MetaIndexParser, (*Target)->MetaKey);
- HashStringList const oldFile = GetExpectedHashesFromFor(TransactionManager->LastMetaIndexParser, (*Target)->MetaKey);
+ HashStringList const newFile = GetExpectedHashesFromFor(TransactionManager->MetaIndexParser, Target->MetaKey);
+ HashStringList const oldFile = GetExpectedHashesFromFor(TransactionManager->LastMetaIndexParser, Target->MetaKey);
if (newFile == oldFile)
{
// we have the file already, no point in trying to acquire it again
continue;
}
}
+ else if (TransactionManager->IMSHit == true)
+ {
+ // we have the file already, no point in trying to acquire it again
+ new NoActionItem(Owner, *Target);
+ continue;
+ }
}
else
trypdiff = false; // no file to patch
// check if we have patches available
- trypdiff &= TransactionManager->MetaIndexParser->Exists((*Target)->MetaKey + ".diff/Index");
+ trypdiff &= TransactionManager->MetaIndexParser->Exists(Target->MetaKey + ".diff/Index");
}
// if we have no file to patch, no point in trying
- trypdiff &= RealFileExists(GetFinalFileNameFromURI((*Target)->URI));
+ trypdiff &= RealFileExists(GetFinalFileNameFromURI(Target->URI));
// no point in patching from local sources
if (trypdiff)
{
- std::string const proto = (*Target)->URI.substr(0, strlen("file:/"));
+ std::string const proto = Target->URI.substr(0, strlen("file:/"));
if (proto == "file:/" || proto == "copy:/" || proto == "cdrom:")
trypdiff = false;
}
Transformed = "";
}
- if (_config->FindB("Acquire::Check-Valid-Until", true) == true &&
- TransactionManager->MetaIndexParser->GetValidUntil() > 0) {
+ if (TransactionManager->MetaIndexParser->GetValidUntil() > 0)
+ {
time_t const invalid_since = time(NULL) - TransactionManager->MetaIndexParser->GetValidUntil();
if (invalid_since > 0)
{
std::string errmsg;
strprintf(errmsg,
// TRANSLATOR: The first %s is the URL of the bad Release file, the second is
- // the time since then the file is invalid - formated in the same way as in
+ // the time since then the file is invalid - formatted in the same way as in
// the download progress display (e.g. 7d 3h 42min 1s)
_("Release file for %s is expired (invalid since %s). "
"Updates for this repository will not be applied."),
- DataTarget.URI.c_str(), TimeToStr(invalid_since).c_str());
+ Target.URI.c_str(), TimeToStr(invalid_since).c_str());
if (ErrorText.empty())
ErrorText = errmsg;
return _error->Error("%s", errmsg.c_str());
TransactionManager->IMSHit = true;
unlink(DestFile.c_str());
PartialFile = DestFile = GetFinalFilename();
- delete TransactionManager->MetaIndexParser;
- TransactionManager->MetaIndexParser = TransactionManager->LastMetaIndexParser;
+ // load the 'old' file in the 'new' one instead of flipping pointers as
+ // the new one isn't owned by us, while the old one is so cleanup would be confused.
+ TransactionManager->MetaIndexParser->swapLoad(TransactionManager->LastMetaIndexParser);
+ delete TransactionManager->LastMetaIndexParser;
TransactionManager->LastMetaIndexParser = NULL;
}
if (_config->FindB("Debug::pkgAcquire::Auth", false))
{
- std::cerr << "Got Codename: " << TransactionManager->MetaIndexParser->GetDist() << std::endl;
+ std::cerr << "Got Codename: " << TransactionManager->MetaIndexParser->GetCodename() << std::endl;
std::cerr << "Expecting Dist: " << TransactionManager->MetaIndexParser->GetExpectedDist() << std::endl;
std::cerr << "Transformed Dist: " << Transformed << std::endl;
}
// Status = StatAuthError;
// ErrorText = "Conflicting distribution; expected "
// + MetaIndexParser->GetExpectedDist() + " but got "
-// + MetaIndexParser->GetDist();
+// + 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->GetDist().c_str());
+ TransactionManager->MetaIndexParser->GetCodename().c_str());
}
}
return true;
}
/*}}}*/
+pkgAcqMetaBase::~pkgAcqMetaBase()
+{
+}
pkgAcqMetaClearSig::pkgAcqMetaClearSig(pkgAcquire * const Owner, /*{{{*/
IndexTarget const &ClearsignedTarget,
IndexTarget const &DetachedDataTarget, IndexTarget const &DetachedSigTarget,
- const vector<IndexTarget*>* const IndexTargets,
- indexRecords * const MetaIndexParser) :
- pkgAcqMetaIndex(Owner, this, ClearsignedTarget, DetachedSigTarget, IndexTargets, MetaIndexParser),
- ClearsignedTarget(ClearsignedTarget),
- DetachedDataTarget(DetachedDataTarget), DetachedSigTarget(DetachedSigTarget)
+ std::vector<IndexTarget> const &IndexTargets,
+ metaIndex * const MetaIndexParser) :
+ pkgAcqMetaIndex(Owner, this, ClearsignedTarget, DetachedSigTarget, IndexTargets),
+ d(NULL), ClearsignedTarget(ClearsignedTarget),
+ DetachedDataTarget(DetachedDataTarget),
+ MetaIndexParser(MetaIndexParser), LastMetaIndexParser(NULL)
{
// index targets + (worst case:) Release/Release.gpg
- ExpectedAdditionalItems = IndexTargets->size() + 2;
+ ExpectedAdditionalItems = IndexTargets.size() + 2;
TransactionManager->Add(this);
}
/*}}}*/
pkgAcqMetaClearSig::~pkgAcqMetaClearSig() /*{{{*/
{
+ if (LastMetaIndexParser != NULL)
+ delete LastMetaIndexParser;
}
/*}}}*/
// pkgAcqMetaClearSig::Custom600Headers - Insert custom request headers /*{{{*/
{
string Header = pkgAcqMetaBase::Custom600Headers();
Header += "\nFail-Ignore: true";
+ std::string const key = TransactionManager->MetaIndexParser->GetSignedBy();
+ if (key.empty() == false)
+ Header += "\nSigned-By: " + key;
+
return Header;
}
/*}}}*/
+bool pkgAcqMetaClearSig::VerifyDone(std::string const &Message,
+ pkgAcquire::MethodConfig const * const Cnf)
+{
+ Item::VerifyDone(Message, Cnf);
+
+ if (FileExists(DestFile) && !StartsWithGPGClearTextSignature(DestFile))
+ return RenameOnError(NotClearsigned);
+
+ return true;
+}
// pkgAcqMetaClearSig::Done - We got a file /*{{{*/
void pkgAcqMetaClearSig::Done(std::string const &Message,
HashStringList const &Hashes,
{
Item::Done(Message, Hashes, Cnf);
- // if we expect a ClearTextSignature (InRelease), ensure that
- // this is what we get and if not fail to queue a
- // Release/Release.gpg, see #346386
- if (FileExists(DestFile) && !StartsWithGPGClearTextSignature(DestFile))
- {
- pkgAcquire::Item::Failed(Message, Cnf);
- RenameOnError(NotClearsigned);
- TransactionManager->AbortTransaction();
- return;
- }
-
if(AuthPass == false)
{
if(CheckDownloadDone(this, Message, Hashes) == true)
// We got an InRelease file IMSHit, but we haven't one, which means
// we had a valid Release/Release.gpg combo stepping in, which we have
// to 'acquire' now to ensure list cleanup isn't removing them
- new NoActionItem(Owner, &DetachedDataTarget);
- new NoActionItem(Owner, &DetachedSigTarget);
+ new NoActionItem(Owner, DetachedDataTarget);
+ new NoActionItem(Owner, DetachedSigTarget);
}
}
}
if (AuthPass == false)
{
+ if (Status == StatAuthError)
+ {
+ // if we expected a ClearTextSignature (InRelease) and got a file,
+ // but it wasn't valid we end up here (see VerifyDone).
+ // As these is usually called by web-portals we do not try Release/Release.gpg
+ // as this is gonna fail anyway and instead abort our try (LP#346386)
+ TransactionManager->AbortTransaction();
+ return;
+ }
+
// Queue the 'old' InRelease file for removal if we try Release.gpg
// as otherwise the file will stay around and gives a false-auth
// impression (CVE-2012-0214)
TransactionManager->TransactionStageRemoval(this, GetFinalFilename());
Status = StatDone;
- new pkgAcqMetaIndex(Owner, TransactionManager, DetachedDataTarget, DetachedSigTarget, IndexTargets, TransactionManager->MetaIndexParser);
+ new pkgAcqMetaIndex(Owner, TransactionManager, DetachedDataTarget, DetachedSigTarget, IndexTargets);
}
else
{
// open the last Release if we have it
if (TransactionManager->IMSHit == false)
{
- TransactionManager->LastMetaIndexParser = new indexRecords;
- _error->PushToStack();
- if (RealFileExists(FinalInRelease))
- TransactionManager->LastMetaIndexParser->Load(FinalInRelease);
- else
- TransactionManager->LastMetaIndexParser->Load(FinalRelease);
- // its unlikely to happen, but if what we have is bad ignore it
- if (_error->PendingError())
+ TransactionManager->LastMetaIndexParser = TransactionManager->MetaIndexParser->UnloadedClone();
+ if (TransactionManager->LastMetaIndexParser != NULL)
{
- delete TransactionManager->LastMetaIndexParser;
- TransactionManager->LastMetaIndexParser = NULL;
+ _error->PushToStack();
+ if (RealFileExists(FinalInRelease))
+ TransactionManager->LastMetaIndexParser->Load(FinalInRelease, NULL);
+ else
+ TransactionManager->LastMetaIndexParser->Load(FinalRelease, NULL);
+ // its unlikely to happen, but if what we have is bad ignore it
+ if (_error->PendingError())
+ {
+ delete TransactionManager->LastMetaIndexParser;
+ TransactionManager->LastMetaIndexParser = NULL;
+ }
+ _error->RevertToStack();
}
- _error->RevertToStack();
}
}
// we parse the indexes here because at this point the user wanted
// a repository that may potentially harm him
- if (TransactionManager->MetaIndexParser->Load(PartialRelease) == false || VerifyVendor(Message) == false)
+ if (TransactionManager->MetaIndexParser->Load(PartialRelease, &ErrorText) == false || VerifyVendor(Message) == false)
/* expired Release files are still a problem you need extra force for */;
else
QueueIndexes(true);
/*}}}*/
pkgAcqMetaIndex::pkgAcqMetaIndex(pkgAcquire * const Owner, /*{{{*/
- pkgAcqMetaBase * const TransactionManager,
+ pkgAcqMetaClearSig * const TransactionManager,
IndexTarget const &DataTarget,
IndexTarget const &DetachedSigTarget,
- vector<IndexTarget*> const * const IndexTargets,
- indexRecords * const MetaIndexParser) :
- pkgAcqMetaBase(Owner, TransactionManager, IndexTargets, DataTarget, MetaIndexParser),
+ vector<IndexTarget> const &IndexTargets) :
+ pkgAcqMetaBase(Owner, TransactionManager, IndexTargets, DataTarget), d(NULL),
DetachedSigTarget(DetachedSigTarget)
{
if(_config->FindB("Debug::Acquire::Transaction", false) == true)
Desc.URI = DataTarget.URI;
// we expect more item
- ExpectedAdditionalItems = IndexTargets->size();
+ ExpectedAdditionalItems = IndexTargets.size();
QueueURI(Desc);
}
/*}}}*/
// we have a Release file, now download the Signature, all further
// verify/queue for additional downloads will be done in the
// pkgAcqMetaSig::Done() code
- new pkgAcqMetaSig(Owner, TransactionManager, &DetachedSigTarget, this);
+ new pkgAcqMetaSig(Owner, TransactionManager, DetachedSigTarget, this);
}
}
/*}}}*/
_error->Warning(_("The repository '%s' does not have a Release file. "
"This is deprecated, please contact the owner of the "
- "repository."), DataTarget.Description.c_str());
+ "repository."), Target.Description.c_str());
// No Release file was present so fall
// back to queueing Packages files without verification
{
// ensure old Release files are removed
TransactionManager->TransactionStageRemoval(this, GetFinalFilename());
- delete TransactionManager->MetaIndexParser;
- TransactionManager->MetaIndexParser = NULL;
// queue without any kind of hashsum support
QueueIndexes(false);
/*}}}*/
std::string pkgAcqMetaIndex::DescURI() const /*{{{*/
{
- return DataTarget.URI;
+ return Target.URI;
}
/*}}}*/
+pkgAcqMetaIndex::~pkgAcqMetaIndex() {}
// AcqMetaSig::AcqMetaSig - Constructor /*{{{*/
pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire * const Owner,
- pkgAcqMetaBase * const TransactionManager,
- IndexTarget const * const Target,
+ pkgAcqMetaClearSig * const TransactionManager,
+ IndexTarget const &Target,
pkgAcqMetaIndex * const MetaIndex) :
- pkgAcqTransactionItem(Owner, TransactionManager, Target), MetaIndex(MetaIndex)
+ pkgAcqTransactionItem(Owner, TransactionManager, Target), d(NULL), MetaIndex(MetaIndex)
{
- DestFile = GetPartialFileNameFromURI(Target->URI);
+ DestFile = GetPartialFileNameFromURI(Target.URI);
// remove any partial downloaded sig-file in partial/.
// it may confuse proxies and is too small to warrant a
<< TransactionManager << std::endl;
// Create the item
- Desc.Description = Target->Description;
+ Desc.Description = Target.Description;
Desc.Owner = this;
- Desc.ShortDesc = Target->ShortDesc;
- Desc.URI = Target->URI;
+ Desc.ShortDesc = Target.ShortDesc;
+ Desc.URI = Target.URI;
// If we got a hit for Release, we will get one for Release.gpg too (or obscure errors),
// so we skip the download step and go instantly to verification
/*}}}*/
pkgAcqMetaSig::~pkgAcqMetaSig() /*{{{*/
{
+}
+ /*}}}*/
+// pkgAcqMetaSig::Custom600Headers - Insert custom request headers /*{{{*/
+std::string pkgAcqMetaSig::Custom600Headers() const
+{
+ std::string Header = pkgAcqTransactionItem::Custom600Headers();
+ std::string const key = TransactionManager->MetaIndexParser->GetSignedBy();
+ if (key.empty() == false)
+ Header += "\nSigned-By: " + key;
+ return Header;
}
/*}}}*/
// AcqMetaSig::Done - The signature was downloaded/verified /*{{{*/
{
std::string downgrade_msg;
strprintf(downgrade_msg, _("The repository '%s' is no longer signed."),
- MetaIndex->DataTarget.Description.c_str());
+ MetaIndex->Target.Description.c_str());
if(_config->FindB("Acquire::AllowDowngradeToInsecureRepositories"))
{
// meh, the users wants to take risks (we still mark the packages
else
_error->Warning(_("The data from '%s' is not signed. Packages "
"from that repository can not be authenticated."),
- MetaIndex->DataTarget.Description.c_str());
+ MetaIndex->Target.Description.c_str());
// ensures that a Release.gpg file in the lists/ is removed by the transaction
TransactionManager->TransactionStageRemoval(this, DestFile);
// open the last Release if we have it
if (TransactionManager->IMSHit == false)
{
- TransactionManager->LastMetaIndexParser = new indexRecords;
- _error->PushToStack();
- if (RealFileExists(FinalInRelease))
- TransactionManager->LastMetaIndexParser->Load(FinalInRelease);
- else
- TransactionManager->LastMetaIndexParser->Load(FinalRelease);
- // its unlikely to happen, but if what we have is bad ignore it
- if (_error->PendingError())
+ TransactionManager->LastMetaIndexParser = TransactionManager->MetaIndexParser->UnloadedClone();
+ if (TransactionManager->LastMetaIndexParser != NULL)
{
- delete TransactionManager->LastMetaIndexParser;
- TransactionManager->LastMetaIndexParser = NULL;
+ _error->PushToStack();
+ if (RealFileExists(FinalInRelease))
+ TransactionManager->LastMetaIndexParser->Load(FinalInRelease, NULL);
+ else
+ TransactionManager->LastMetaIndexParser->Load(FinalRelease, NULL);
+ // its unlikely to happen, but if what we have is bad ignore it
+ if (_error->PendingError())
+ {
+ delete TransactionManager->LastMetaIndexParser;
+ TransactionManager->LastMetaIndexParser = NULL;
+ }
+ _error->RevertToStack();
}
- _error->RevertToStack();
}
}
// we parse the indexes here because at this point the user wanted
// a repository that may potentially harm him
- if (TransactionManager->MetaIndexParser->Load(MetaIndex->DestFile) == false || MetaIndex->VerifyVendor(Message) == false)
+ if (TransactionManager->MetaIndexParser->Load(MetaIndex->DestFile, &ErrorText) == false || MetaIndex->VerifyVendor(Message) == false)
/* expired Release files are still a problem you need extra force for */;
else
MetaIndex->QueueIndexes(true);
// AcqBaseIndex - Constructor /*{{{*/
pkgAcqBaseIndex::pkgAcqBaseIndex(pkgAcquire * const Owner,
- pkgAcqMetaBase * const TransactionManager,
- IndexTarget const * const Target)
-: pkgAcqTransactionItem(Owner, TransactionManager, Target)
+ pkgAcqMetaClearSig * const TransactionManager,
+ IndexTarget const &Target)
+: pkgAcqTransactionItem(Owner, TransactionManager, Target), d(NULL)
{
}
/*}}}*/
+pkgAcqBaseIndex::~pkgAcqBaseIndex() {}
// AcqDiffIndex::AcqDiffIndex - Constructor /*{{{*/
// ---------------------------------------------------------------------
* the original packages file
*/
pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire * const Owner,
- pkgAcqMetaBase * const TransactionManager,
- IndexTarget const * const Target)
- : pkgAcqBaseIndex(Owner, TransactionManager, Target)
+ pkgAcqMetaClearSig * const TransactionManager,
+ IndexTarget const &Target)
+ : pkgAcqBaseIndex(Owner, TransactionManager, Target), d(NULL), diffs(NULL)
{
Debug = _config->FindB("Debug::pkgAcquire::Diffs",false);
Desc.Owner = this;
- Desc.Description = Target->Description + ".diff/Index";
- Desc.ShortDesc = Target->ShortDesc;
- Desc.URI = Target->URI + ".diff/Index";
+ Desc.Description = Target.Description + ".diff/Index";
+ Desc.ShortDesc = Target.ShortDesc;
+ Desc.URI = Target.URI + ".diff/Index";
DestFile = GetPartialFileNameFromURI(Desc.URI);
return false;
}
- std::string const CurrentPackagesFile = GetFinalFileNameFromURI(Target->URI);
- HashStringList const TargetFileHashes = GetExpectedHashesFor(Target->MetaKey);
+ std::string const CurrentPackagesFile = GetFinalFileNameFromURI(Target.URI);
+ HashStringList const TargetFileHashes = GetExpectedHashesFor(Target.MetaKey);
if (TargetFileHashes.usable() == false || ServerHashes != TargetFileHashes)
{
if (Debug == true)
HashStringList LocalHashes;
// try avoiding calculating the hash here as this is costly
if (TransactionManager->LastMetaIndexParser != NULL)
- LocalHashes = GetExpectedHashesFromFor(TransactionManager->LastMetaIndexParser, Target->MetaKey);
+ LocalHashes = GetExpectedHashesFromFor(TransactionManager->LastMetaIndexParser, Target.MetaKey);
if (LocalHashes.usable() == false)
{
FileFd fd(CurrentPackagesFile, FileFd::ReadOnly);
new pkgAcqIndexDiffs(Owner, TransactionManager, Target, available_patches);
else
{
- std::vector<pkgAcqIndexMergeDiffs*> *diffs = new std::vector<pkgAcqIndexMergeDiffs*>(available_patches.size());
+ 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,
return;
}
/*}}}*/
+pkgAcqDiffIndex::~pkgAcqDiffIndex()
+{
+ if (diffs != NULL)
+ delete diffs;
+}
// AcqIndexDiffs::AcqIndexDiffs - Constructor /*{{{*/
// ---------------------------------------------------------------------
* for each diff and the index
*/
pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire * const Owner,
- pkgAcqMetaBase * const TransactionManager,
- IndexTarget const * const Target,
+ pkgAcqMetaClearSig * const TransactionManager,
+ IndexTarget const &Target,
vector<DiffInfo> const &diffs)
- : pkgAcqBaseIndex(Owner, TransactionManager, Target),
+ : pkgAcqBaseIndex(Owner, TransactionManager, Target), d(NULL),
available_patches(diffs)
{
- DestFile = GetPartialFileNameFromURI(Target->URI);
+ DestFile = GetPartialFileNameFromURI(Target.URI);
Debug = _config->FindB("Debug::pkgAcquire::Diffs",false);
Desc.Owner = this;
- Description = Target->Description;
- Desc.ShortDesc = Target->ShortDesc;
+ Description = Target.Description;
+ Desc.ShortDesc = Target.ShortDesc;
if(available_patches.empty() == true)
{
// we are done (yeah!), check hashes against the final file
- DestFile = GetFinalFileNameFromURI(Target->URI);
+ DestFile = GetFinalFileNameFromURI(Target.URI);
Finish(true);
}
else
{
// patching needs to be bootstrapped with the 'old' version
- std::string const PartialFile = GetPartialFileNameFromURI(Target->URI);
+ std::string const PartialFile = GetPartialFileNameFromURI(Target.URI);
if (RealFileExists(PartialFile) == false)
{
if (symlink(GetFinalFilename().c_str(), PartialFile.c_str()) != 0)
if(Debug)
std::clog << "pkgAcqIndexDiffs failed: " << Desc.URI << " with " << Message << std::endl
<< "Falling back to normal index file acquire" << std::endl;
- DestFile = GetPartialFileNameFromURI(Target->URI);
+ DestFile = GetPartialFileNameFromURI(Target.URI);
RenameOnError(PDiffError);
std::string const patchname = GetDiffsPatchFileName(DestFile);
if (RealFileExists(patchname))
bool pkgAcqIndexDiffs::QueueNextDiff() /*{{{*/
{
// calc sha1 of the just patched file
- std::string const FinalFile = GetPartialFileNameFromURI(Target->URI);
+ std::string const FinalFile = GetPartialFileNameFromURI(Target.URI);
if(!FileExists(FinalFile))
{
if(Debug)
std::clog << "QueueNextDiff: " << FinalFile << " (" << LocalHashes.find(NULL)->toStr() << ")" << std::endl;
- HashStringList const TargetFileHashes = GetExpectedHashesFor(Target->MetaKey);
+ HashStringList const TargetFileHashes = GetExpectedHashesFor(Target.MetaKey);
if (unlikely(LocalHashes.usable() == false || TargetFileHashes.usable() == false))
{
Failed("Local/Expected hashes are not usable", NULL);
}
// queue the right diff
- Desc.URI = Target->URI + ".diff/" + available_patches[0].file + ".gz";
+ Desc.URI = Target.URI + ".diff/" + available_patches[0].file + ".gz";
Desc.Description = Description + " " + available_patches[0].file + string(".pdiff");
- DestFile = GetPartialFileNameFromURI(Target->URI + ".diff/" + available_patches[0].file);
+ DestFile = GetPartialFileNameFromURI(Target.URI + ".diff/" + available_patches[0].file);
if(Debug)
std::clog << "pkgAcqIndexDiffs::QueueNextDiff(): " << Desc.URI << std::endl;
Item::Done(Message, Hashes, Cnf);
- std::string const FinalFile = GetPartialFileNameFromURI(Target->URI);
+ std::string const FinalFile = GetPartialFileNameFromURI(Target.URI);
std::string const PatchFile = GetDiffsPatchFileName(FinalFile);
// success in downloading a diff, enter ApplyDiff state
return patchhashes.str();
}
/*}}}*/
+pkgAcqIndexDiffs::~pkgAcqIndexDiffs() {}
// AcqIndexMergeDiffs::AcqIndexMergeDiffs - Constructor /*{{{*/
pkgAcqIndexMergeDiffs::pkgAcqIndexMergeDiffs(pkgAcquire * const Owner,
- pkgAcqMetaBase * const TransactionManager,
- IndexTarget const * const Target,
+ pkgAcqMetaClearSig * const TransactionManager,
+ IndexTarget const &Target,
DiffInfo const &patch,
std::vector<pkgAcqIndexMergeDiffs*> const * const allPatches)
- : pkgAcqBaseIndex(Owner, TransactionManager, Target),
+ : pkgAcqBaseIndex(Owner, TransactionManager, Target), d(NULL),
patch(patch), allPatches(allPatches), State(StateFetchDiff)
{
Debug = _config->FindB("Debug::pkgAcquire::Diffs",false);
Desc.Owner = this;
- Description = Target->Description;
- Desc.ShortDesc = Target->ShortDesc;
+ Description = Target.Description;
+ Desc.ShortDesc = Target.ShortDesc;
- Desc.URI = Target->URI + ".diff/" + patch.file + ".gz";
+ Desc.URI = Target.URI + ".diff/" + patch.file + ".gz";
Desc.Description = Description + " " + patch.file + string(".pdiff");
- DestFile = GetPartialFileNameFromURI(Target->URI + ".diff/" + patch.file);
+ DestFile = GetPartialFileNameFromURI(Target.URI + ".diff/" + patch.file);
if(Debug)
std::clog << "pkgAcqIndexMergeDiffs: " << Desc.URI << std::endl;
State = StateErrorDiff;
if (Debug)
std::clog << "Falling back to normal index file acquire" << std::endl;
- DestFile = GetPartialFileNameFromURI(Target->URI);
+ DestFile = GetPartialFileNameFromURI(Target.URI);
RenameOnError(PDiffError);
std::string const patchname = GetMergeDiffsPatchFileName(DestFile, patch.file);
if (RealFileExists(patchname))
Item::Done(Message, Hashes, Cnf);
- string const FinalFile = GetPartialFileNameFromURI(Target->URI);
+ string const FinalFile = GetPartialFileNameFromURI(Target.URI);
if (State == StateFetchDiff)
{
Rename(DestFile, GetMergeDiffsPatchFileName(FinalFile, patch.file));
for (std::vector<pkgAcqIndexMergeDiffs *>::const_iterator I = allPatches->begin();
I != allPatches->end(); ++I)
{
- std::string const PartialFile = GetPartialFileNameFromURI(Target->URI);
+ std::string const PartialFile = GetPartialFileNameFromURI(Target.URI);
std::string const patch = GetMergeDiffsPatchFileName(PartialFile, (*I)->patch.file);
unlink(patch.c_str());
}
return patchhashes.str();
}
/*}}}*/
+pkgAcqIndexMergeDiffs::~pkgAcqIndexMergeDiffs() {}
// AcqIndex::AcqIndex - Constructor /*{{{*/
pkgAcqIndex::pkgAcqIndex(pkgAcquire * const Owner,
- pkgAcqMetaBase * const TransactionManager,
- IndexTarget const * const Target)
- : pkgAcqBaseIndex(Owner, TransactionManager, Target)
+ pkgAcqMetaClearSig * const TransactionManager,
+ IndexTarget const &Target)
+ : pkgAcqBaseIndex(Owner, TransactionManager, Target), d(NULL), Stage(STAGE_DOWNLOAD)
{
// autoselect the compression method
AutoSelectCompression();
- Init(Target->URI, Target->Description, Target->ShortDesc);
+ Init(Target.URI, Target.Description, Target.ShortDesc);
if(_config->FindB("Debug::Acquire::Transaction", false) == true)
std::clog << "New pkgIndex with TransactionManager "
{
std::vector<std::string> types = APT::Configuration::getCompressionTypes();
CompressionExtensions = "";
- if (TransactionManager->MetaIndexParser != NULL && TransactionManager->MetaIndexParser->Exists(Target->MetaKey))
+ if (TransactionManager->MetaIndexParser != NULL && TransactionManager->MetaIndexParser->Exists(Target.MetaKey))
{
for (std::vector<std::string>::const_iterator t = types.begin();
t != types.end(); ++t)
{
- std::string CompressedMetaKey = string(Target->MetaKey).append(".").append(*t);
+ std::string CompressedMetaKey = string(Target.MetaKey).append(".").append(*t);
if (*t == "uncompressed" ||
TransactionManager->MetaIndexParser->Exists(CompressedMetaKey) == true)
CompressionExtensions.append(*t).append(" ");
if (stat(Final.c_str(),&Buf) == 0)
msg += "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
- if(Target->IsOptional)
+ if(Target.IsOptional)
msg += "\nFail-Ignore: true";
return msg;
{
if (CompressionExtensions.empty() == false)
{
- Init(Target->URI, Desc.Description, Desc.ShortDesc);
+ Init(Target.URI, Desc.Description, Desc.ShortDesc);
Status = StatIdle;
return;
}
}
- if(Target->IsOptional && GetExpectedHashes().empty() && Stage == STAGE_DOWNLOAD)
+ if(Target.IsOptional && GetExpectedHashes().empty() && Stage == STAGE_DOWNLOAD)
Status = StatDone;
else
TransactionManager->AbortTransaction();
{
// update destfile to *not* include the compression extension when doing
// a reverify (as its uncompressed on disk already)
- DestFile = GetCompressedFileName(Target->URI, GetPartialFileNameFromURI(Target->URI), CurrentCompressionExtension);
+ DestFile = GetCompressedFileName(Target, GetPartialFileNameFromURI(Target.URI), CurrentCompressionExtension);
// copy FinalFile into partial/ so that we check the hash again
string FinalFile = GetFinalFilename();
Complete = true;
// Handle the unzipd case
- string FileName = LookupTag(Message,"Alt-Filename");
+ std::string FileName = LookupTag(Message,"Alt-Filename");
if (FileName.empty() == false)
{
Stage = STAGE_DECOMPRESS_AND_VERIFY;
SetActiveSubprocess("copy");
return;
}
-
FileName = LookupTag(Message,"Filename");
- if (FileName.empty() == true)
- {
- Status = StatError;
- ErrorText = "Method gave a blank filename";
- }
// Methods like e.g. "file:" will give us a (compressed) FileName that is
// not the "DestFile" we set, in this case we uncompress from the local file
- if (FileName != DestFile)
+ if (FileName != DestFile && RealFileExists(DestFile) == false)
Local = true;
else
EraseFileName = FileName;
return;
}
- // If we have compressed indexes enabled, queue for hash verification
- if (_config->FindB("Acquire::GzipIndexes",false))
+ // If we want compressed indexes, just copy in place for hash verification
+ if (Target.KeepCompressed == true)
{
- DestFile = GetPartialFileNameFromURI(Target->URI + '.' + CurrentCompressionExtension);
+ DestFile = GetPartialFileNameFromURI(Target.URI + '.' + CurrentCompressionExtension);
EraseFileName = "";
Stage = STAGE_DECOMPRESS_AND_VERIFY;
Desc.URI = "copy:" + FileName;
return;
}
/*}}}*/
+pkgAcqIndex::~pkgAcqIndex() {}
// AcqArchive::AcqArchive - Constructor /*{{{*/
pkgAcqArchive::pkgAcqArchive(pkgAcquire * const Owner,pkgSourceList * const Sources,
pkgRecords * const Recs,pkgCache::VerIterator const &Version,
string &StoreFilename) :
- Item(Owner), LocalSource(false), Version(Version), Sources(Sources), Recs(Recs),
+ Item(Owner), d(NULL), LocalSource(false), Version(Version), Sources(Sources), Recs(Recs),
StoreFilename(StoreFilename), Vf(Version.FileList()),
Trusted(false)
{
// Skip not source sources, they do not have file fields.
for (; Vf.end() == false; ++Vf)
{
- if ((Vf.File()->Flags & pkgCache::Flag::NotSource) != 0)
+ if (Vf.File().Flagged(pkgCache::Flag::NotSource))
continue;
break;
}
{
pkgCache::PkgFileIterator const PkgF = Vf.File();
// Ignore not source sources
- if ((PkgF->Flags & pkgCache::Flag::NotSource) != 0)
+ if (PkgF.Flagged(pkgCache::Flag::NotSource))
continue;
// Try to cross match against the source list
pkgIndexFile *Index;
if (Sources->FindIndex(PkgF, Index) == false)
continue;
- LocalSource = (PkgF->Flags & pkgCache::Flag::LocalSource) == pkgCache::Flag::LocalSource;
+ LocalSource = PkgF.Flagged(pkgCache::Flag::LocalSource);
// only try to get a trusted package from another source if that source
// is also trusted
Item::Done(Message, Hashes, Cfg);
// Grab the output filename
- string FileName = LookupTag(Message,"Filename");
- if (FileName.empty() == true)
- {
- Status = StatError;
- ErrorText = "Method gave a blank filename";
- return;
- }
-
- // Reference filename
- if (FileName != DestFile)
+ std::string const FileName = LookupTag(Message,"Filename");
+ if (DestFile != FileName && RealFileExists(DestFile) == false)
{
StoreFilename = DestFile = FileName;
Local = true;
return Desc.ShortDesc;
}
/*}}}*/
+pkgAcqArchive::~pkgAcqArchive() {}
+
+// AcqChangelog::pkgAcqChangelog - Constructors /*{{{*/
+pkgAcqChangelog::pkgAcqChangelog(pkgAcquire * const Owner, pkgCache::VerIterator const &Ver,
+ std::string const &DestDir, std::string const &DestFilename) :
+ pkgAcquire::Item(Owner), d(NULL), SrcName(Ver.SourcePkgName()), SrcVersion(Ver.SourceVerStr())
+{
+ Desc.URI = URI(Ver);
+ Init(DestDir, DestFilename);
+}
+// some parameters are char* here as they come likely from char* interfaces – which can also return NULL
+pkgAcqChangelog::pkgAcqChangelog(pkgAcquire * const Owner, pkgCache::RlsFileIterator const &RlsFile,
+ char const * const Component, char const * const SrcName, char const * const SrcVersion,
+ const string &DestDir, const string &DestFilename) :
+ pkgAcquire::Item(Owner), d(NULL), SrcName(SrcName), SrcVersion(SrcVersion)
+{
+ Desc.URI = URI(RlsFile, Component, SrcName, SrcVersion);
+ Init(DestDir, DestFilename);
+}
+pkgAcqChangelog::pkgAcqChangelog(pkgAcquire * const Owner,
+ std::string const &URI, char const * const SrcName, char const * const SrcVersion,
+ const string &DestDir, const string &DestFilename) :
+ pkgAcquire::Item(Owner), d(NULL), SrcName(SrcName), SrcVersion(SrcVersion)
+{
+ Desc.URI = URI;
+ Init(DestDir, DestFilename);
+}
+void pkgAcqChangelog::Init(std::string const &DestDir, std::string const &DestFilename)
+{
+ if (Desc.URI.empty())
+ {
+ Status = StatError;
+ // TRANSLATOR: %s=%s is sourcename=sourceversion, e.g. apt=1.1
+ strprintf(ErrorText, _("Changelog unavailable for %s=%s"), SrcName.c_str(), SrcVersion.c_str());
+ // Let the error message print something sensible rather than "Failed to fetch /"
+ if (DestFilename.empty())
+ DestFile = SrcName + ".changelog";
+ else
+ DestFile = DestFilename;
+ Desc.URI = "changelog:/" + DestFile;
+ return;
+ }
+
+ if (DestDir.empty())
+ {
+ std::string const systemTemp = GetTempDir();
+ char tmpname[100];
+ snprintf(tmpname, sizeof(tmpname), "%s/apt-changelog-XXXXXX", systemTemp.c_str());
+ if (NULL == mkdtemp(tmpname))
+ {
+ _error->Errno("mkdtemp", "mkdtemp failed in changelog acquire of %s %s", SrcName.c_str(), SrcVersion.c_str());
+ Status = StatError;
+ return;
+ }
+ DestFile = TemporaryDirectory = tmpname;
+ }
+ else
+ DestFile = DestDir;
+
+ if (DestFilename.empty())
+ DestFile = flCombine(DestFile, SrcName + ".changelog");
+ else
+ DestFile = flCombine(DestFile, DestFilename);
+
+ Desc.ShortDesc = "Changelog";
+ strprintf(Desc.Description, "%s %s %s Changelog", URI::SiteOnly(Desc.URI).c_str(), SrcName.c_str(), SrcVersion.c_str());
+ Desc.Owner = this;
+ QueueURI(Desc);
+}
+ /*}}}*/
+std::string pkgAcqChangelog::URI(pkgCache::VerIterator const &Ver) /*{{{*/
+{
+ char const * const SrcName = Ver.SourcePkgName();
+ char const * const SrcVersion = Ver.SourceVerStr();
+ pkgCache::PkgFileIterator PkgFile;
+ // find the first source for this version which promises a changelog
+ for (pkgCache::VerFileIterator VF = Ver.FileList(); VF.end() == false; ++VF)
+ {
+ pkgCache::PkgFileIterator const PF = VF.File();
+ if (PF.Flagged(pkgCache::Flag::NotSource) || PF->Release == 0)
+ continue;
+ PkgFile = PF;
+ pkgCache::RlsFileIterator const RF = PF.ReleaseFile();
+ std::string const uri = URI(RF, PF.Component(), SrcName, SrcVersion);
+ if (uri.empty())
+ continue;
+ return uri;
+ }
+ return "";
+}
+std::string pkgAcqChangelog::URITemplate(pkgCache::RlsFileIterator const &Rls)
+{
+ if (Rls.end() == true || (Rls->Label == 0 && Rls->Origin == 0))
+ return "";
+ std::string const serverConfig = "Acquire::Changelogs::URI";
+ std::string server;
+#define APT_EMPTY_SERVER \
+ if (server.empty() == false) \
+ { \
+ if (server != "no") \
+ return server; \
+ return ""; \
+ }
+#define APT_CHECK_SERVER(X, Y) \
+ if (Rls->X != 0) \
+ { \
+ std::string const specialServerConfig = serverConfig + "::" + Y + #X + "::" + Rls.X(); \
+ server = _config->Find(specialServerConfig); \
+ APT_EMPTY_SERVER \
+ }
+ // this way e.g. Debian-Security can fallback to Debian
+ APT_CHECK_SERVER(Label, "Override::")
+ APT_CHECK_SERVER(Origin, "Override::")
+
+ if (RealFileExists(Rls.FileName()))
+ {
+ _error->PushToStack();
+ FileFd rf;
+ /* This can be costly. A caller wanting to get millions of URIs might
+ want to do this on its own once and use Override settings.
+ We don't do this here as Origin/Label are not as unique as they
+ should be so this could produce request order-dependent anomalies */
+ if (OpenMaybeClearSignedFile(Rls.FileName(), rf) == true)
+ {
+ pkgTagFile TagFile(&rf, rf.Size());
+ pkgTagSection Section;
+ if (TagFile.Step(Section) == true)
+ server = Section.FindS("Changelogs");
+ }
+ _error->RevertToStack();
+ APT_EMPTY_SERVER
+ }
+
+ APT_CHECK_SERVER(Label, "")
+ APT_CHECK_SERVER(Origin, "")
+#undef APT_CHECK_SERVER
+#undef APT_EMPTY_SERVER
+ return "";
+}
+std::string pkgAcqChangelog::URI(pkgCache::RlsFileIterator const &Rls,
+ char const * const Component, char const * const SrcName,
+ char const * const SrcVersion)
+{
+ return URI(URITemplate(Rls), Component, SrcName, SrcVersion);
+}
+std::string pkgAcqChangelog::URI(std::string const &Template,
+ char const * const Component, char const * const SrcName,
+ char const * const SrcVersion)
+{
+ if (Template.find("CHANGEPATH") == std::string::npos)
+ return "";
+
+ // the path is: COMPONENT/SRC/SRCNAME/SRCNAME_SRCVER, e.g. main/a/apt/1.1 or contrib/liba/libapt/2.0
+ std::string Src = SrcName;
+ std::string path = APT::String::Startswith(SrcName, "lib") ? Src.substr(0, 4) : Src.substr(0,1);
+ path.append("/").append(Src).append("/");
+ path.append(Src).append("_").append(StripEpoch(SrcVersion));
+ // we omit component for releases without one (= flat-style repositories)
+ if (Component != NULL && strlen(Component) != 0)
+ path = std::string(Component) + "/" + path;
+
+ return SubstVar(Template, "CHANGEPATH", path);
+}
+ /*}}}*/
+// AcqChangelog::Failed - Failure handler /*{{{*/
+void pkgAcqChangelog::Failed(string const &Message, pkgAcquire::MethodConfig const * const Cnf)
+{
+ Item::Failed(Message,Cnf);
+
+ std::string errText;
+ // TRANSLATOR: %s=%s is sourcename=sourceversion, e.g. apt=1.1
+ strprintf(errText, _("Changelog unavailable for %s=%s"), SrcName.c_str(), SrcVersion.c_str());
+
+ // Error is probably something techy like 404 Not Found
+ if (ErrorText.empty())
+ ErrorText = errText;
+ else
+ ErrorText = errText + " (" + ErrorText + ")";
+ return;
+}
+ /*}}}*/
+// AcqChangelog::Done - Item downloaded OK /*{{{*/
+void pkgAcqChangelog::Done(string const &Message,HashStringList const &CalcHashes,
+ pkgAcquire::MethodConfig const * const Cnf)
+{
+ Item::Done(Message,CalcHashes,Cnf);
+
+ Complete = true;
+}
+ /*}}}*/
+pkgAcqChangelog::~pkgAcqChangelog() /*{{{*/
+{
+ if (TemporaryDirectory.empty() == false)
+ {
+ unlink(DestFile.c_str());
+ rmdir(TemporaryDirectory.c_str());
+ }
+}
+ /*}}}*/
// AcqFile::pkgAcqFile - Constructor /*{{{*/
pkgAcqFile::pkgAcqFile(pkgAcquire * const Owner,string const &URI, HashStringList const &Hashes,
unsigned long long const Size,string const &Dsc,string const &ShortDesc,
const string &DestDir, const string &DestFilename,
bool const IsIndexFile) :
- Item(Owner), IsIndexFile(IsIndexFile), ExpectedHashes(Hashes)
+ Item(Owner), d(NULL), IsIndexFile(IsIndexFile), ExpectedHashes(Hashes)
{
Retries = _config->FindI("Acquire::Retries",0);
{
Item::Done(Message,CalcHashes,Cnf);
- string FileName = LookupTag(Message,"Filename");
- if (FileName.empty() == true)
- {
- Status = StatError;
- ErrorText = "Method gave a blank filename";
- return;
- }
-
+ std::string const FileName = LookupTag(Message,"Filename");
Complete = true;
// The files timestamp matches
return;
// We have to copy it into place
- if (FileName != DestFile)
+ if (RealFileExists(DestFile.c_str()) == false)
{
Local = true;
if (_config->FindB("Acquire::Source-Symlinks",true) == false ||
return "";
}
/*}}}*/
+pkgAcqFile::~pkgAcqFile() {}