diff options
author | Michael Vogt <mvo@debian.org> | 2015-08-18 11:57:35 +0200 |
---|---|---|
committer | Michael Vogt <mvo@debian.org> | 2015-08-18 11:57:35 +0200 |
commit | b53c9cea2902572822bbbece5bac236c1bbf846e (patch) | |
tree | 6c6b0524e0971c0623ccbff71383523ee0b2a5cc /apt-pkg | |
parent | 21248c0f00ee71412dbadc6ebf84011cf974346d (diff) | |
parent | 2a22cd60f04c4291ea9b9b72e15b6d2ec378b001 (diff) |
Merge remote-tracking branch 'upstream/debian/experimental' into feature/srv-records
Diffstat (limited to 'apt-pkg')
109 files changed, 7037 insertions, 6417 deletions
diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 8155b9bfe..26c835444 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -22,15 +22,15 @@ #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> @@ -41,9 +41,9 @@ #include <unistd.h> #include <errno.h> #include <string> -#include <sstream> #include <stdio.h> #include <ctime> +#include <sstream> #include <apti18n.h> /*}}}*/ @@ -79,25 +79,38 @@ static std::string GetFinalFileNameFromURI(std::string const &uri) /*{{{*/ 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 std::string GetMergeDiffsPatchFileName(std::string const &Final, std::string const &Patch)/*{{{*/ +{ + // rred expects the patch as $FinalFile.ed.$patchname.gz + return Final + ".ed." + Patch + ".gz"; +} + /*}}}*/ +static std::string GetDiffsPatchFileName(std::string const &Final) /*{{{*/ +{ + // rred expects the patch as $FinalFile.ed + return Final + ".ed"; +} + /*}}}*/ + +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")); @@ -106,41 +119,343 @@ static bool AllowInsecureRepositories(indexRecords const * const MetaIndexParser return false; } /*}}}*/ +static HashStringList GetExpectedHashesFromFor(metaIndex * const Parser, std::string const &MetaKey)/*{{{*/ +{ + if (Parser == NULL) + return HashStringList(); + metaIndex::checkSum * const R = Parser->Lookup(MetaKey); + if (R == NULL) + return HashStringList(); + return R->Hashes; +} + /*}}}*/ + +// all ::HashesRequired and ::GetExpectedHashes implementations /*{{{*/ +/* ::GetExpectedHashes is abstract and has to be implemented by all subclasses. + It is best to implement it as broadly as possible, while ::HashesRequired defaults + to true and should be as restrictive as possible for false cases. Note that if + a hash is returned by ::GetExpectedHashes it must match. Only if it doesn't + ::HashesRequired is called to evaluate if its okay to have no hashes. */ +APT_CONST bool pkgAcqTransactionItem::HashesRequired() const +{ + /* signed repositories obviously have a parser and good hashes. + unsigned repositories, too, as even if we can't trust them for security, + 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 && + TransactionManager->MetaIndexParser->GetLoadedSuccessfully() != metaIndex::TRI_UNSET; +} +HashStringList pkgAcqTransactionItem::GetExpectedHashes() const +{ + return GetExpectedHashesFor(GetMetaKey()); +} + +APT_CONST bool pkgAcqMetaBase::HashesRequired() const +{ + // Release and co have no hashes 'by design'. + return false; +} +HashStringList pkgAcqMetaBase::GetExpectedHashes() const +{ + return HashStringList(); +} + +APT_CONST bool pkgAcqIndexDiffs::HashesRequired() const +{ + /* We don't always have the diff of the downloaded pdiff file. + What we have for sure is hashes for the uncompressed file, + but rred uncompresses them on the fly while parsing, so not handled here. + Hashes are (also) checked while searching for (next) patch to apply. */ + if (State == StateFetchDiff) + return available_patches[0].download_hashes.empty() == false; + return false; +} +HashStringList pkgAcqIndexDiffs::GetExpectedHashes() const +{ + if (State == StateFetchDiff) + return available_patches[0].download_hashes; + return HashStringList(); +} + +APT_CONST bool pkgAcqIndexMergeDiffs::HashesRequired() const +{ + /* @see #pkgAcqIndexDiffs::HashesRequired, with the difference that + we can check the rred result after all patches are applied as + we know the expected result rather than potentially apply more patches */ + if (State == StateFetchDiff) + return patch.download_hashes.empty() == false; + return State == StateApplyDiff; +} +HashStringList pkgAcqIndexMergeDiffs::GetExpectedHashes() const +{ + if (State == StateFetchDiff) + return patch.download_hashes; + else if (State == StateApplyDiff) + return GetExpectedHashesFor(Target.MetaKey); + return HashStringList(); +} + +APT_CONST bool pkgAcqArchive::HashesRequired() const +{ + return LocalSource == false; +} +HashStringList pkgAcqArchive::GetExpectedHashes() const +{ + // figured out while parsing the records + return ExpectedHashes; +} + +APT_CONST bool pkgAcqFile::HashesRequired() const +{ + // supplied as parameter at creation time, so the caller decides + return ExpectedHashes.usable(); +} +HashStringList pkgAcqFile::GetExpectedHashes() const +{ + return ExpectedHashes; +} + /*}}}*/ +// Acquire::Item::QueueURI and specialisations from child classes /*{{{*/ +bool pkgAcquire::Item::QueueURI(pkgAcquire::ItemDesc &Item) +{ + Owner->Enqueue(Item); + return true; +} +/* The idea here is that an item isn't queued if it exists on disk and the + transition manager was a hit as this means that the files it contains + the checksums for can't be updated either (or they are and we are asking + for a hashsum mismatch to happen which helps nobody) */ +bool pkgAcqTransactionItem::QueueURI(pkgAcquire::ItemDesc &Item) +{ + std::string const FinalFile = GetFinalFilename(); + if (TransactionManager != NULL && TransactionManager->IMSHit == true && + FileExists(FinalFile) == true) + { + PartialFile = DestFile = FinalFile; + Status = StatDone; + return false; + } + return pkgAcquire::Item::QueueURI(Item); +} +/* The transition manager InRelease itself (or its older sisters-in-law + Release & Release.gpg) is always queued as this allows us to rerun gpgv + on it to verify that we aren't stalled with old files */ +bool pkgAcqMetaBase::QueueURI(pkgAcquire::ItemDesc &Item) +{ + return pkgAcquire::Item::QueueURI(Item); +} +/* the Diff/Index needs to queue also the up-to-date complete index file + to ensure that the list cleaner isn't eating it */ +bool pkgAcqDiffIndex::QueueURI(pkgAcquire::ItemDesc &Item) +{ + if (pkgAcqTransactionItem::QueueURI(Item) == true) + return true; + QueueOnIMSHit(); + return false; +} + /*}}}*/ +// Acquire::Item::GetFinalFilename and specialisations for child classes /*{{{*/ +std::string pkgAcquire::Item::GetFinalFilename() const +{ + return GetFinalFileNameFromURI(Desc.URI); +} +std::string pkgAcqDiffIndex::GetFinalFilename() const +{ + // the logic we inherent from pkgAcqBaseIndex isn't what we need here + return pkgAcquire::Item::GetFinalFilename(); +} +std::string pkgAcqIndex::GetFinalFilename() const +{ + std::string const FinalFile = GetFinalFileNameFromURI(Target.URI); + return GetCompressedFileName(Target, FinalFile, CurrentCompressionExtension); +} +std::string pkgAcqMetaSig::GetFinalFilename() const +{ + return GetFinalFileNameFromURI(Target.URI); +} +std::string pkgAcqBaseIndex::GetFinalFilename() const +{ + return GetFinalFileNameFromURI(Target.URI); +} +std::string pkgAcqMetaBase::GetFinalFilename() const +{ + return GetFinalFileNameFromURI(Target.URI); +} +std::string pkgAcqArchive::GetFinalFilename() const +{ + return _config->FindDir("Dir::Cache::Archives") + flNotDir(StoreFilename); +} + /*}}}*/ +// pkgAcqTransactionItem::GetMetaKey and specialisations for child classes /*{{{*/ +std::string pkgAcqTransactionItem::GetMetaKey() const +{ + return Target.MetaKey; +} +std::string pkgAcqIndex::GetMetaKey() const +{ + if (Stage == STAGE_DECOMPRESS_AND_VERIFY || CurrentCompressionExtension == "uncompressed") + return Target.MetaKey; + return Target.MetaKey + "." + CurrentCompressionExtension; +} +std::string pkgAcqDiffIndex::GetMetaKey() const +{ + return Target.MetaKey + ".diff/Index"; +} + /*}}}*/ +//pkgAcqTransactionItem::TransactionState and specialisations for child classes /*{{{*/ +bool pkgAcqTransactionItem::TransactionState(TransactionStates const state) +{ + bool const Debug = _config->FindB("Debug::Acquire::Transaction", false); + switch(state) + { + case TransactionAbort: + if(Debug == true) + std::clog << " Cancel: " << DestFile << std::endl; + if (Status == pkgAcquire::Item::StatIdle) + { + Status = pkgAcquire::Item::StatDone; + Dequeue(); + } + break; + case TransactionCommit: + if(PartialFile != "") + { + if(Debug == true) + std::clog << "mv " << PartialFile << " -> "<< DestFile << " # " << DescURI() << std::endl; + + Rename(PartialFile, DestFile); + } else { + if(Debug == true) + std::clog << "rm " << DestFile << " # " << DescURI() << std::endl; + unlink(DestFile.c_str()); + } + break; + } + return true; +} +bool pkgAcqMetaBase::TransactionState(TransactionStates const state) +{ + // Do not remove InRelease on IMSHit of Release.gpg [yes, this is very edgecasey] + if (TransactionManager->IMSHit == false) + return pkgAcqTransactionItem::TransactionState(state); + return true; +} +bool pkgAcqIndex::TransactionState(TransactionStates const state) +{ + if (pkgAcqTransactionItem::TransactionState(state) == false) + return false; + + switch (state) + { + case TransactionAbort: + if (Stage == STAGE_DECOMPRESS_AND_VERIFY) + { + // keep the compressed file, but drop the decompressed + EraseFileName.clear(); + if (PartialFile.empty() == false && flExtension(PartialFile) == "decomp") + unlink(PartialFile.c_str()); + } + break; + case TransactionCommit: + if (EraseFileName.empty() == false) + unlink(EraseFileName.c_str()); + break; + } + return true; +} +bool pkgAcqDiffIndex::TransactionState(TransactionStates const state) +{ + if (pkgAcqTransactionItem::TransactionState(state) == false) + return false; + + switch (state) + { + case TransactionCommit: + break; + case TransactionAbort: + std::string const Partial = GetPartialFileNameFromURI(Target.URI); + unlink(Partial.c_str()); + break; + } + + return true; +} + /*}}}*/ +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 Target; + public: + virtual std::string DescURI() const APT_OVERRIDE {return Target.URI;}; + virtual HashStringList GetExpectedHashes() const APT_OVERRIDE {return HashStringList();}; + + NoActionItem(pkgAcquire * const Owner, IndexTarget const &Target) : + pkgAcquire::Item(Owner), Target(Target) + { + Status = StatDone; + DestFile = GetFinalFileNameFromURI(Target.URI); + } +}; + /*}}}*/ // Acquire::Item::Item - Constructor /*{{{*/ APT_IGNORE_DEPRECATED_PUSH -pkgAcquire::Item::Item(pkgAcquire *Owner, - HashStringList const &ExpectedHashes, - pkgAcqMetaBase *TransactionManager) - : Owner(Owner), FileSize(0), PartialSize(0), Mode(0), ID(0), Complete(false), - Local(false), QueueCounter(0), TransactionManager(TransactionManager), - ExpectedAdditionalItems(0), ExpectedHashes(ExpectedHashes) +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; - if(TransactionManager != NULL) - TransactionManager->Add(this); } APT_IGNORE_DEPRECATED_POP /*}}}*/ // Acquire::Item::~Item - Destructor /*{{{*/ -// --------------------------------------------------------------------- -/* */ pkgAcquire::Item::~Item() { Owner->Remove(this); } /*}}}*/ +std::string pkgAcquire::Item::Custom600Headers() const /*{{{*/ +{ + return std::string(); +} + /*}}}*/ +std::string pkgAcquire::Item::ShortDesc() const /*{{{*/ +{ + return DescURI(); +} + /*}}}*/ +APT_CONST void pkgAcquire::Item::Finished() /*{{{*/ +{ +} + /*}}}*/ +APT_PURE pkgAcquire * pkgAcquire::Item::GetOwner() const /*{{{*/ +{ + return Owner; +} + /*}}}*/ +APT_CONST pkgAcquire::ItemDesc &pkgAcquire::Item::GetItemDesc() /*{{{*/ +{ + return Desc; +} + /*}}}*/ +APT_CONST bool pkgAcquire::Item::IsTrusted() const /*{{{*/ +{ + return false; +} + /*}}}*/ // Acquire::Item::Failed - Item failed to download /*{{{*/ // --------------------------------------------------------------------- /* We return to an idle state if there are still other queues that could fetch this object */ -void pkgAcquire::Item::Failed(string Message,pkgAcquire::MethodConfig *Cnf) +void pkgAcquire::Item::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf) { 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 @@ -154,63 +469,43 @@ void pkgAcquire::Item::Failed(string Message,pkgAcquire::MethodConfig *Cnf) return; } - Status = StatError; + switch (Status) + { + case StatIdle: + case StatFetching: + case StatDone: + Status = StatError; + break; + case StatAuthError: + case StatError: + case StatTransientNetworkError: + break; + } Complete = false; Dequeue(); } - else - Status = StatIdle; - // check fail reason string const FailReason = LookupTag(Message, "FailReason"); - if(FailReason == "MaximumSizeExceeded") + if (FailReason == "MaximumSizeExceeded") RenameOnError(MaximumSizeExceeded); + else if (Status == StatAuthError) + RenameOnError(HashSumMismatch); // report mirror failure back to LP if we actually use a mirror - if(FailReason.size() != 0) + if (FailReason.empty() == false) ReportMirrorFailure(FailReason); else ReportMirrorFailure(ErrorText); -} - /*}}}*/ -bool pkgAcquire::Item::TransactionState(TransactionStates const state) /*{{{*/ -{ - bool const Debug = _config->FindB("Debug::Acquire::Transaction", false); - switch(state) - { - case TransactionAbort: - if(Debug == true) - std::clog << " Cancel: " << DestFile << std::endl; - if (Status == pkgAcquire::Item::StatIdle) - { - Status = pkgAcquire::Item::StatDone; - Dequeue(); - } - break; - case TransactionCommit: - if(PartialFile != "") - { - if(Debug == true) - std::clog << "mv " << PartialFile << " -> "<< DestFile << " # " << DescURI() << std::endl; - Rename(PartialFile, DestFile); - } else { - if(Debug == true) - std::clog << "rm " << DestFile << " # " << DescURI() << std::endl; - unlink(DestFile.c_str()); - } - // mark that this transaction is finished - TransactionManager = 0; - break; - } - return true; + if (QueueCounter > 1) + Status = StatIdle; } /*}}}*/ // Acquire::Item::Start - Item has begun to download /*{{{*/ // --------------------------------------------------------------------- -/* Stash status and the file size. Note that setting Complete means +/* Stash status and the file size. Note that setting Complete means sub-phases of the acquire process such as decompresion are operating */ -void pkgAcquire::Item::Start(string /*Message*/,unsigned long long Size) +void pkgAcquire::Item::Start(string const &/*Message*/, unsigned long long const Size) { Status = StatFetching; ErrorText.clear(); @@ -218,23 +513,36 @@ void pkgAcquire::Item::Start(string /*Message*/,unsigned long long Size) FileSize = Size; } /*}}}*/ -// Acquire::Item::Done - Item downloaded OK /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void pkgAcquire::Item::Done(string Message,unsigned long long Size,HashStringList const &/*Hash*/, - pkgAcquire::MethodConfig * /*Cnf*/) +// 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*/) { - // We just downloaded something.. - string FileName = LookupTag(Message,"Filename"); - UsedMirror = LookupTag(Message,"UsedMirror"); - if (Complete == false && !Local && FileName == DestFile) + std::string const FileName = LookupTag(Message,"Filename"); + if (FileName.empty() == true) { - if (Owner->Log != 0) - Owner->Log->Fetched(Size,atoi(LookupTag(Message,"Resume-Point","0").c_str())); + 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, + pkgAcquire::MethodConfig const * const /*Cnf*/) +{ + // We just downloaded something.. if (FileSize == 0) - FileSize= Size; + { + unsigned long long const downloadedSize = Hashes.FileSize(); + if (downloadedSize != 0) + { + FileSize = downloadedSize; + } + } Status = StatDone; ErrorText = string(); Owner->Dequeue(this); @@ -244,7 +552,7 @@ void pkgAcquire::Item::Done(string Message,unsigned long long Size,HashStringLis // --------------------------------------------------------------------- /* This helper function is used by a lot of item methods as their final step */ -bool pkgAcquire::Item::Rename(string From,string To) +bool pkgAcquire::Item::Rename(string const &From,string const &To) { if (From == To || rename(From.c_str(),To.c_str()) == 0) return true; @@ -260,43 +568,6 @@ bool pkgAcquire::Item::Rename(string From,string To) return false; } /*}}}*/ -// Acquire::Item::QueueURI and specialisations from child classes /*{{{*/ -/* The idea here is that an item isn't queued if it exists on disk and the - transition manager was a hit as this means that the files it contains - the checksums for can't be updated either (or they are and we are asking - for a hashsum mismatch to happen which helps nobody) */ -bool pkgAcquire::Item::QueueURI(ItemDesc &Item) -{ - std::string const FinalFile = GetFinalFilename(); - if (TransactionManager != NULL && TransactionManager->IMSHit == true && - FileExists(FinalFile) == true) - { - PartialFile = DestFile = FinalFile; - Status = StatDone; - return false; - } - - Owner->Enqueue(Item); - return true; -} -/* The transition manager InRelease itself (or its older sisters-in-law - Release & Release.gpg) is always queued as this allows us to rerun gpgv - on it to verify that we aren't stalled with old files */ -bool pkgAcqMetaBase::QueueURI(pkgAcquire::ItemDesc &Item) -{ - Owner->Enqueue(Item); - return true; -} -/* the Diff/Index needs to queue also the up-to-date complete index file - to ensure that the list cleaner isn't eating it */ -bool pkgAcqDiffIndex::QueueURI(pkgAcquire::ItemDesc &Item) -{ - if (pkgAcquire::Item::QueueURI(Item) == true) - return true; - QueueOnIMSHit(); - return false; -} - /*}}}*/ void pkgAcquire::Item::Dequeue() /*{{{*/ { Owner->Dequeue(this); @@ -307,30 +578,31 @@ bool pkgAcquire::Item::RenameOnError(pkgAcquire::Item::RenameOnErrorState const if (RealFileExists(DestFile)) Rename(DestFile, DestFile + ".FAILED"); + std::string errtext; switch (error) { case HashSumMismatch: - ErrorText = _("Hash Sum mismatch"); + errtext = _("Hash Sum mismatch"); Status = StatAuthError; ReportMirrorFailure("HashChecksumFailure"); break; case SizeMismatch: - ErrorText = _("Size mismatch"); + errtext = _("Size mismatch"); Status = StatAuthError; ReportMirrorFailure("SizeFailure"); break; case InvalidFormat: - ErrorText = _("Invalid file format"); + errtext = _("Invalid file format"); Status = StatError; // do not report as usually its not the mirrors fault, but Portal/Proxy break; case SignatureError: - ErrorText = _("Signature error"); + errtext = _("Signature error"); Status = StatError; break; case NotClearsigned: - ErrorText = _("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 @@ -340,6 +612,8 @@ bool pkgAcquire::Item::RenameOnError(pkgAcquire::Item::RenameOnErrorState const // no handling here, done by callers break; } + if (ErrorText.empty()) + ErrorText = errtext; return false; } /*}}}*/ @@ -349,15 +623,8 @@ void pkgAcquire::Item::SetActiveSubprocess(const std::string &subprocess)/*{{{*/ APT_IGNORE_DEPRECATED(Mode = ActiveSubprocess.c_str();) } /*}}}*/ -// Acquire::Item::GetFinalFilename - Return the full final file path /*{{{*/ -std::string pkgAcquire::Item::GetFinalFilename() const -{ - return GetFinalFileNameFromURI(Desc.URI); -} - /*}}}*/ // Acquire::Item::ReportMirrorFailure /*{{{*/ -// --------------------------------------------------------------------- -void pkgAcquire::Item::ReportMirrorFailure(string FailCode) +void pkgAcquire::Item::ReportMirrorFailure(string const &FailCode) { // we only act if a mirror was used at all if(UsedMirror.empty()) @@ -400,6 +667,881 @@ void pkgAcquire::Item::ReportMirrorFailure(string FailCode) } } /*}}}*/ +std::string pkgAcquire::Item::HashSum() const /*{{{*/ +{ + HashStringList const hashes = GetExpectedHashes(); + HashString const * const hs = hashes.find(NULL); + return hs != NULL ? hs->toStr() : ""; +} + /*}}}*/ + +pkgAcqTransactionItem::pkgAcqTransactionItem(pkgAcquire * const Owner, /*{{{*/ + pkgAcqMetaClearSig * const transactionManager, IndexTarget const &target) : + pkgAcquire::Item(Owner), d(NULL), Target(target), TransactionManager(transactionManager) +{ + if (TransactionManager != this) + TransactionManager->Add(this); +} + /*}}}*/ +pkgAcqTransactionItem::~pkgAcqTransactionItem() /*{{{*/ +{ +} + /*}}}*/ +HashStringList pkgAcqTransactionItem::GetExpectedHashesFor(std::string const &MetaKey) const /*{{{*/ +{ + return GetExpectedHashesFromFor(TransactionManager->MetaIndexParser, MetaKey); +} + /*}}}*/ + +// AcqMetaBase - Constructor /*{{{*/ +pkgAcqMetaBase::pkgAcqMetaBase(pkgAcquire * const Owner, + pkgAcqMetaClearSig * const TransactionManager, + std::vector<IndexTarget> const &IndexTargets, + IndexTarget const &DataTarget) +: pkgAcqTransactionItem(Owner, TransactionManager, DataTarget), d(NULL), + IndexTargets(IndexTargets), + AuthPass(false), IMSHit(false) +{ +} + /*}}}*/ +// AcqMetaBase::Add - Add a item to the current Transaction /*{{{*/ +void pkgAcqMetaBase::Add(pkgAcqTransactionItem * const I) +{ + Transaction.push_back(I); +} + /*}}}*/ +// AcqMetaBase::AbortTransaction - Abort the current Transaction /*{{{*/ +void pkgAcqMetaBase::AbortTransaction() +{ + if(_config->FindB("Debug::Acquire::Transaction", false) == true) + std::clog << "AbortTransaction: " << TransactionManager << std::endl; + + // ensure the toplevel is in error state too + for (std::vector<pkgAcqTransactionItem*>::iterator I = Transaction.begin(); + I != Transaction.end(); ++I) + { + (*I)->TransactionState(TransactionAbort); + } + Transaction.clear(); +} + /*}}}*/ +// AcqMetaBase::TransactionHasError - Check for errors in Transaction /*{{{*/ +APT_PURE bool pkgAcqMetaBase::TransactionHasError() const +{ + for (std::vector<pkgAcqTransactionItem*>::const_iterator I = Transaction.begin(); + I != Transaction.end(); ++I) + { + switch((*I)->Status) { + case StatDone: break; + case StatIdle: break; + case StatAuthError: return true; + case StatError: return true; + case StatTransientNetworkError: return true; + case StatFetching: break; + } + } + return false; +} + /*}}}*/ +// AcqMetaBase::CommitTransaction - Commit a transaction /*{{{*/ +void pkgAcqMetaBase::CommitTransaction() +{ + if(_config->FindB("Debug::Acquire::Transaction", false) == true) + std::clog << "CommitTransaction: " << this << std::endl; + + // move new files into place *and* remove files that are not + // part of the transaction but are still on disk + for (std::vector<pkgAcqTransactionItem*>::iterator I = Transaction.begin(); + I != Transaction.end(); ++I) + { + (*I)->TransactionState(TransactionCommit); + } + Transaction.clear(); +} + /*}}}*/ +// AcqMetaBase::TransactionStageCopy - Stage a file for copying /*{{{*/ +void pkgAcqMetaBase::TransactionStageCopy(pkgAcqTransactionItem * const I, + const std::string &From, + const std::string &To) +{ + I->PartialFile = From; + I->DestFile = To; +} + /*}}}*/ +// AcqMetaBase::TransactionStageRemoval - Stage a file for removal /*{{{*/ +void pkgAcqMetaBase::TransactionStageRemoval(pkgAcqTransactionItem * const I, + const std::string &FinalFile) +{ + I->PartialFile = ""; + I->DestFile = FinalFile; +} + /*}}}*/ +// AcqMetaBase::GenerateAuthWarning - Check gpg authentication error /*{{{*/ +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)) + { + 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()); + 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()); + I->Status = StatAuthError; + return true; + } else { + _error->Warning(_("GPG error: %s: %s"), + Desc.Description.c_str(), + LookupTag(Message,"Message").c_str()); + } + // gpgv method failed + ReportMirrorFailure("GPGFailure"); + return false; +} + /*}}}*/ +// AcqMetaBase::Custom600Headers - Get header for AcqMetaBase /*{{{*/ +// --------------------------------------------------------------------- +string pkgAcqMetaBase::Custom600Headers() const +{ + std::string Header = "\nIndex-File: true"; + std::string MaximumSize; + strprintf(MaximumSize, "\nMaximum-Size: %i", + _config->FindI("Acquire::MaxReleaseFileSize", 10*1000*1000)); + Header += MaximumSize; + + string const FinalFile = GetFinalFilename(); + struct stat Buf; + if (stat(FinalFile.c_str(),&Buf) == 0) + Header += "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime); + + return Header; +} + /*}}}*/ +// AcqMetaBase::QueueForSignatureVerify /*{{{*/ +void pkgAcqMetaBase::QueueForSignatureVerify(pkgAcqTransactionItem * const I, std::string const &File, std::string const &Signature) +{ + AuthPass = true; + I->Desc.URI = "gpgv:" + Signature; + I->DestFile = File; + QueueURI(I->Desc); + I->SetActiveSubprocess("gpgv"); +} + /*}}}*/ +// AcqMetaBase::CheckDownloadDone /*{{{*/ +bool pkgAcqMetaBase::CheckDownloadDone(pkgAcqTransactionItem * const I, const std::string &Message, HashStringList const &Hashes) const +{ + // We have just finished downloading a Release file (it is not + // verified yet) + + std::string const FileName = LookupTag(Message,"Filename"); + if (FileName != I->DestFile && RealFileExists(I->DestFile) == false) + { + I->Local = true; + I->Desc.URI = "copy:" + FileName; + I->QueueURI(I->Desc); + return false; + } + + // make sure to verify against the right file on I-M-S hit + bool IMSHit = StringToBool(LookupTag(Message,"IMS-Hit"), false); + if (IMSHit == false && Hashes.usable()) + { + // detect IMS-Hits servers haven't detected by Hash comparison + std::string const FinalFile = I->GetFinalFilename(); + if (RealFileExists(FinalFile) && Hashes.VerifyFile(FinalFile) == true) + { + IMSHit = true; + unlink(I->DestFile.c_str()); + } + } + + if(IMSHit == true) + { + // for simplicity, the transaction manager is always InRelease + // even if it doesn't exist. + if (TransactionManager != NULL) + TransactionManager->IMSHit = true; + I->PartialFile = I->DestFile = I->GetFinalFilename(); + } + + // set Item to complete as the remaining work is all local (verify etc) + I->Complete = true; + + return true; +} + /*}}}*/ +bool pkgAcqMetaBase::CheckAuthDone(string const &Message) /*{{{*/ +{ + // At this point, the gpgv method has succeeded, so there is a + // valid signature from a key in the trusted keyring. We + // perform additional verification of its contents, and use them + // to verify the indexes we are about to download + + if (TransactionManager->IMSHit == false) + { + // open the last (In)Release if we have it + std::string const FinalFile = GetFinalFilename(); + std::string FinalRelease; + std::string FinalInRelease; + if (APT::String::Endswith(FinalFile, "InRelease")) + { + FinalInRelease = FinalFile; + FinalRelease = FinalFile.substr(0, FinalFile.length() - strlen("InRelease")) + "Release"; + } + else + { + FinalInRelease = FinalFile.substr(0, FinalFile.length() - strlen("Release")) + "InRelease"; + FinalRelease = FinalFile; + } + if (RealFileExists(FinalInRelease) || RealFileExists(FinalRelease)) + { + TransactionManager->LastMetaIndexParser = TransactionManager->MetaIndexParser->UnloadedClone(); + if (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(); + } + } + } + + if (TransactionManager->MetaIndexParser->Load(DestFile, &ErrorText) == false) + { + Status = StatAuthError; + return false; + } + + if (!VerifyVendor(Message)) + { + Status = StatAuthError; + return false; + } + + if (_config->FindB("Debug::pkgAcquire::Auth", false)) + std::cerr << "Signature verification succeeded: " + << DestFile << std::endl; + + // Download further indexes with verification + QueueIndexes(true); + + return true; +} + /*}}}*/ +void pkgAcqMetaBase::QueueIndexes(bool const verify) /*{{{*/ +{ + // at this point the real Items are loaded in the fetcher + ExpectedAdditionalItems = 0; + + 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) + { + // optional targets that we do not have in the Release file are skipped + 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()); + return; + } + + 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); + if (newFile == oldFile) + { + // we have the file already, no point in trying to acquire it again + new NoActionItem(Owner, *Target); + 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"); + } + // if we have no file to patch, no point in trying + trypdiff &= RealFileExists(GetFinalFileNameFromURI(Target->URI)); + + // no point in patching from local sources + if (trypdiff) + { + std::string const proto = Target->URI.substr(0, strlen("file:/")); + if (proto == "file:/" || proto == "copy:/" || proto == "cdrom:") + trypdiff = false; + } + + // Queue the Index file (Packages, Sources, Translation-$foo, …) + if (trypdiff) + new pkgAcqDiffIndex(Owner, TransactionManager, *Target); + else + new pkgAcqIndex(Owner, TransactionManager, *Target); + } +} + /*}}}*/ +bool pkgAcqMetaBase::VerifyVendor(string const &Message) /*{{{*/ +{ + 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('/'); + 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(); + 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 - 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."), + Target.URI.c_str(), TimeToStr(invalid_since).c_str()); + if (ErrorText.empty()) + ErrorText = errmsg; + return _error->Error("%s", errmsg.c_str()); + } + } + + /* Did we get a file older than what we have? This is a last minute IMS hit and doubles + as a prevention of downgrading us to older (still valid) files */ + if (TransactionManager->IMSHit == false && TransactionManager->LastMetaIndexParser != NULL && + TransactionManager->LastMetaIndexParser->GetDate() > TransactionManager->MetaIndexParser->GetDate()) + { + TransactionManager->IMSHit = true; + unlink(DestFile.c_str()); + PartialFile = DestFile = GetFinalFilename(); + // 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->GetCodename() << std::endl; + std::cerr << "Expecting Dist: " << TransactionManager->MetaIndexParser->GetExpectedDist() << std::endl; + std::cerr << "Transformed Dist: " << Transformed << std::endl; + } + + if (TransactionManager->MetaIndexParser->CheckDist(Transformed) == false) + { + // 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()); + } + } + + return true; +} + /*}}}*/ +pkgAcqMetaBase::~pkgAcqMetaBase() +{ +} + +pkgAcqMetaClearSig::pkgAcqMetaClearSig(pkgAcquire * const Owner, /*{{{*/ + IndexTarget const &ClearsignedTarget, + IndexTarget const &DetachedDataTarget, IndexTarget const &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; + TransactionManager->Add(this); +} + /*}}}*/ +pkgAcqMetaClearSig::~pkgAcqMetaClearSig() /*{{{*/ +{ + if (LastMetaIndexParser != NULL) + delete LastMetaIndexParser; +} + /*}}}*/ +// pkgAcqMetaClearSig::Custom600Headers - Insert custom request headers /*{{{*/ +string pkgAcqMetaClearSig::Custom600Headers() const +{ + 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, + pkgAcquire::MethodConfig const * const Cnf) +{ + Item::Done(Message, Hashes, Cnf); + + if(AuthPass == false) + { + if(CheckDownloadDone(this, Message, Hashes) == true) + QueueForSignatureVerify(this, DestFile, DestFile); + return; + } + else if(CheckAuthDone(Message) == true) + { + if (TransactionManager->IMSHit == false) + TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename()); + else if (RealFileExists(GetFinalFilename()) == false) + { + // 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); + } + } +} + /*}}}*/ +void pkgAcqMetaClearSig::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf) /*{{{*/ +{ + Item::Failed(Message, Cnf); + + // we failed, we will not get additional items from this method + ExpectedAdditionalItems = 0; + + 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); + } + else + { + if(CheckStopAuthentication(this, Message)) + return; + + _error->Warning(_("The data from '%s' is not signed. Packages " + "from that repository can not be authenticated."), + ClearsignedTarget.Description.c_str()); + + // No Release file was present, or verification failed, so fall + // back to queueing Packages files without verification + // only allow going further if the users explicitely wants it + if(AllowInsecureRepositories(TransactionManager->MetaIndexParser, TransactionManager, this) == true) + { + Status = StatDone; + + /* InRelease files become Release files, otherwise + * they would be considered as trusted later on */ + string const FinalRelease = GetFinalFileNameFromURI(DetachedDataTarget.URI); + string const PartialRelease = GetPartialFileNameFromURI(DetachedDataTarget.URI); + string const FinalReleasegpg = GetFinalFileNameFromURI(DetachedSigTarget.URI); + string const FinalInRelease = GetFinalFilename(); + Rename(DestFile, PartialRelease); + TransactionManager->TransactionStageCopy(this, PartialRelease, FinalRelease); + + if (RealFileExists(FinalReleasegpg) || RealFileExists(FinalInRelease)) + { + // open the last Release if we have it + if (TransactionManager->IMSHit == false) + { + TransactionManager->LastMetaIndexParser = TransactionManager->MetaIndexParser->UnloadedClone(); + if (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(); + } + } + } + + // we parse the indexes here because at this point the user wanted + // a repository that may potentially harm him + 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, /*{{{*/ + pkgAcqMetaClearSig * const TransactionManager, + IndexTarget const &DataTarget, + IndexTarget const &DetachedSigTarget, + vector<IndexTarget> const &IndexTargets) : + pkgAcqMetaBase(Owner, TransactionManager, IndexTargets, DataTarget), d(NULL), + DetachedSigTarget(DetachedSigTarget) +{ + if(_config->FindB("Debug::Acquire::Transaction", false) == true) + std::clog << "New pkgAcqMetaIndex with TransactionManager " + << this->TransactionManager << std::endl; + + DestFile = GetPartialFileNameFromURI(DataTarget.URI); + + // Create the item + Desc.Description = DataTarget.Description; + Desc.Owner = this; + Desc.ShortDesc = DataTarget.ShortDesc; + Desc.URI = DataTarget.URI; + + // we expect more item + ExpectedAdditionalItems = IndexTargets.size(); + QueueURI(Desc); +} + /*}}}*/ +void pkgAcqMetaIndex::Done(string const &Message, /*{{{*/ + HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cfg) +{ + Item::Done(Message,Hashes,Cfg); + + if(CheckDownloadDone(this, Message, Hashes)) + { + // 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); + } +} + /*}}}*/ +// pkgAcqMetaIndex::Failed - no Release file present /*{{{*/ +void pkgAcqMetaIndex::Failed(string const &Message, + pkgAcquire::MethodConfig const * const Cnf) +{ + pkgAcquire::Item::Failed(Message, Cnf); + Status = StatDone; + + _error->Warning(_("The repository '%s' does not have a Release file. " + "This is deprecated, please contact the owner of the " + "repository."), Target.Description.c_str()); + + // No Release file was present so fall + // back to queueing Packages files without verification + // only allow going further if the users explicitely wants it + if(AllowInsecureRepositories(TransactionManager->MetaIndexParser, TransactionManager, this) == true) + { + // ensure old Release files are removed + TransactionManager->TransactionStageRemoval(this, GetFinalFilename()); + + // queue without any kind of hashsum support + QueueIndexes(false); + } +} + /*}}}*/ +void pkgAcqMetaIndex::Finished() /*{{{*/ +{ + if(_config->FindB("Debug::Acquire::Transaction", false) == true) + std::clog << "Finished: " << DestFile <<std::endl; + if(TransactionManager != NULL && + TransactionManager->TransactionHasError() == false) + TransactionManager->CommitTransaction(); +} + /*}}}*/ +std::string pkgAcqMetaIndex::DescURI() const /*{{{*/ +{ + return Target.URI; +} + /*}}}*/ +pkgAcqMetaIndex::~pkgAcqMetaIndex() {} + +// AcqMetaSig::AcqMetaSig - Constructor /*{{{*/ +pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire * const Owner, + pkgAcqMetaClearSig * const TransactionManager, + IndexTarget const &Target, + pkgAcqMetaIndex * const MetaIndex) : + pkgAcqTransactionItem(Owner, TransactionManager, Target), d(NULL), MetaIndex(MetaIndex) +{ + DestFile = GetPartialFileNameFromURI(Target.URI); + + // remove any partial downloaded sig-file in partial/. + // it may confuse proxies and is too small to warrant a + // partial download anyway + unlink(DestFile.c_str()); + + // set the TransactionManager + if(_config->FindB("Debug::Acquire::Transaction", false) == true) + std::clog << "New pkgAcqMetaSig with TransactionManager " + << TransactionManager << std::endl; + + // Create the item + Desc.Description = Target.Description; + Desc.Owner = this; + 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 + if (TransactionManager->IMSHit == true && RealFileExists(GetFinalFilename())) + { + Complete = true; + Status = StatDone; + PartialFile = DestFile = GetFinalFilename(); + MetaIndexFileSignature = DestFile; + MetaIndex->QueueForSignatureVerify(this, MetaIndex->DestFile, DestFile); + } + else + QueueURI(Desc); +} + /*}}}*/ +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 /*{{{*/ +void pkgAcqMetaSig::Done(string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cfg) +{ + if (MetaIndexFileSignature.empty() == false) + { + DestFile = MetaIndexFileSignature; + MetaIndexFileSignature.clear(); + } + Item::Done(Message, Hashes, Cfg); + + if(MetaIndex->AuthPass == false) + { + if(MetaIndex->CheckDownloadDone(this, Message, Hashes) == true) + { + // destfile will be modified to point to MetaIndexFile for the + // gpgv method, so we need to save it here + MetaIndexFileSignature = DestFile; + MetaIndex->QueueForSignatureVerify(this, MetaIndex->DestFile, DestFile); + } + return; + } + else if(MetaIndex->CheckAuthDone(Message) == true) + { + if (TransactionManager->IMSHit == false) + { + TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename()); + TransactionManager->TransactionStageCopy(MetaIndex, MetaIndex->DestFile, MetaIndex->GetFinalFilename()); + } + } +} + /*}}}*/ +void pkgAcqMetaSig::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf)/*{{{*/ +{ + Item::Failed(Message,Cnf); + + // check if we need to fail at this point + if (MetaIndex->AuthPass == true && MetaIndex->CheckStopAuthentication(this, Message)) + return; + + string const FinalRelease = MetaIndex->GetFinalFilename(); + string const FinalReleasegpg = GetFinalFilename(); + string const FinalInRelease = TransactionManager->GetFinalFilename(); + + if (RealFileExists(FinalReleasegpg) || RealFileExists(FinalInRelease)) + { + std::string downgrade_msg; + strprintf(downgrade_msg, _("The repository '%s' is no longer signed."), + MetaIndex->Target.Description.c_str()); + if(_config->FindB("Acquire::AllowDowngradeToInsecureRepositories")) + { + // meh, the users wants to take risks (we still mark the packages + // from this repository as unauthenticated) + _error->Warning("%s", downgrade_msg.c_str()); + _error->Warning(_("This is normally not allowed, but the option " + "Acquire::AllowDowngradeToInsecureRepositories was " + "given to override it.")); + Status = StatDone; + } else { + _error->Error("%s", downgrade_msg.c_str()); + if (TransactionManager->IMSHit == false) + Rename(MetaIndex->DestFile, MetaIndex->DestFile + ".FAILED"); + Item::Failed("Message: " + downgrade_msg, Cnf); + TransactionManager->AbortTransaction(); + return; + } + } + else + _error->Warning(_("The data from '%s' is not signed. Packages " + "from that repository can not be authenticated."), + MetaIndex->Target.Description.c_str()); + + // ensures that a Release.gpg file in the lists/ is removed by the transaction + TransactionManager->TransactionStageRemoval(this, DestFile); + + // only allow going further if the users explicitely wants it + if(AllowInsecureRepositories(TransactionManager->MetaIndexParser, TransactionManager, this) == true) + { + if (RealFileExists(FinalReleasegpg) || RealFileExists(FinalInRelease)) + { + // open the last Release if we have it + if (TransactionManager->IMSHit == false) + { + TransactionManager->LastMetaIndexParser = TransactionManager->MetaIndexParser->UnloadedClone(); + if (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(); + } + } + } + + // 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, &ErrorText) == false || MetaIndex->VerifyVendor(Message) == false) + /* expired Release files are still a problem you need extra force for */; + else + MetaIndex->QueueIndexes(true); + + TransactionManager->TransactionStageCopy(MetaIndex, MetaIndex->DestFile, MetaIndex->GetFinalFilename()); + } + + // FIXME: this is used often (e.g. in pkgAcqIndexTrans) so refactor + if (Cnf->LocalOnly == true || + StringToBool(LookupTag(Message,"Transient-Failure"),false) == false) + { + // Ignore this + Status = StatDone; + } +} + /*}}}*/ + + +// AcqBaseIndex - Constructor /*{{{*/ +pkgAcqBaseIndex::pkgAcqBaseIndex(pkgAcquire * const Owner, + pkgAcqMetaClearSig * const TransactionManager, + IndexTarget const &Target) +: pkgAcqTransactionItem(Owner, TransactionManager, Target), d(NULL) +{ +} + /*}}}*/ +pkgAcqBaseIndex::~pkgAcqBaseIndex() {} + // AcqDiffIndex::AcqDiffIndex - Constructor /*{{{*/ // --------------------------------------------------------------------- /* Get the DiffIndex file first and see if there are patches available @@ -407,65 +1549,30 @@ void pkgAcquire::Item::ReportMirrorFailure(string FailCode) * patches. If anything goes wrong in that process, it will fall back to * the original packages file */ -pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner, - pkgAcqMetaBase *TransactionManager, - IndexTarget const * const Target, - HashStringList const &ExpectedHashes, - indexRecords *MetaIndexParser) - : pkgAcqBaseIndex(Owner, TransactionManager, Target, ExpectedHashes, - MetaIndexParser) +pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire * const Owner, + pkgAcqMetaClearSig * const TransactionManager, + IndexTarget const &Target) + : pkgAcqBaseIndex(Owner, TransactionManager, Target), d(NULL), diffs(NULL) { - Debug = _config->FindB("Debug::pkgAcquire::Diffs",false); - RealURI = Target->URI; 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); if(Debug) std::clog << "pkgAcqDiffIndex: " << Desc.URI << std::endl; - // look for the current package file - CurrentPackagesFile = GetFinalFileNameFromURI(RealURI); - - // FIXME: this file:/ check is a hack to prevent fetching - // from local sources. this is really silly, and - // should be fixed cleanly as soon as possible - if(!FileExists(CurrentPackagesFile) || - Desc.URI.substr(0,strlen("file:/")) == "file:/") - { - // we don't have a pkg file or we don't want to queue - Failed("No index file, local or canceld by user", NULL); - return; - } - - if(Debug) - std::clog << "pkgAcqDiffIndex::pkgAcqDiffIndex(): " - << CurrentPackagesFile << std::endl; - QueueURI(Desc); - -} - /*}}}*/ -// Acquire::Item::GetFinalFilename - Return the full final file path /*{{{*/ -std::string pkgAcqDiffIndex::GetFinalFilename() const -{ - // the logic we inherent from pkgAcqBaseIndex isn't what we need here - return pkgAcquire::Item::GetFinalFilename(); } /*}}}*/ // AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/ // --------------------------------------------------------------------- /* The only header we use is the last-modified header. */ -#if APT_PKG_ABI >= 413 string pkgAcqDiffIndex::Custom600Headers() const -#else -string pkgAcqDiffIndex::Custom600Headers() -#endif { string const Final = GetFinalFilename(); @@ -483,11 +1590,10 @@ void pkgAcqDiffIndex::QueueOnIMSHit() const /*{{{*/ { // 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, - ExpectedHashes, MetaIndexParser); + new pkgAcqIndexDiffs(Owner, TransactionManager, Target); } /*}}}*/ -bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile) /*{{{*/ +bool pkgAcqDiffIndex::ParseDiffIndex(string const &IndexDiffFile) /*{{{*/ { // failing here is fine: our caller will take care of trying to // get the complete file if patching fails @@ -534,17 +1640,31 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile) /*{{{*/ return false; } - if (ServerHashes != HashSums()) + std::string const CurrentPackagesFile = GetFinalFileNameFromURI(Target.URI); + HashStringList const TargetFileHashes = GetExpectedHashesFor(Target.MetaKey); + if (TargetFileHashes.usable() == false || ServerHashes != TargetFileHashes) { if (Debug == true) { std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": Index has different hashes than parser, probably older, so fail pdiffing" << std::endl; - printHashSumComparision(CurrentPackagesFile, ServerHashes, HashSums()); + printHashSumComparision(CurrentPackagesFile, ServerHashes, TargetFileHashes); } return false; } - if (ServerHashes.VerifyFile(CurrentPackagesFile) == true) + HashStringList LocalHashes; + // try avoiding calculating the hash here as this is costly + if (TransactionManager->LastMetaIndexParser != NULL) + LocalHashes = GetExpectedHashesFromFor(TransactionManager->LastMetaIndexParser, Target.MetaKey); + if (LocalHashes.usable() == false) + { + FileFd fd(CurrentPackagesFile, FileFd::ReadOnly); + Hashes LocalHashesCalc(ServerHashes); + LocalHashesCalc.AddFD(fd); + LocalHashes = LocalHashesCalc.GetHashStringList(); + } + + if (ServerHashes == LocalHashes) { // we have the same sha1 as the server so we are done here if(Debug) @@ -553,14 +1673,9 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile) /*{{{*/ return true; } - FileFd fd(CurrentPackagesFile, FileFd::ReadOnly); - Hashes LocalHashesCalc; - LocalHashesCalc.AddFD(fd); - HashStringList const LocalHashes = LocalHashesCalc.GetHashStringList(); - if(Debug) std::clog << "Server-Current: " << ServerHashes.find(NULL)->toStr() << " and we start at " - << fd.Name() << " " << fd.FileSize() << " " << LocalHashes.find(NULL)->toStr() << std::endl; + << CurrentPackagesFile << " " << LocalHashes.FileSize() << " " << LocalHashes.find(NULL)->toStr() << std::endl; // parse all of (provided) history vector<DiffInfo> available_patches; @@ -589,7 +1704,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile) /*{{{*/ std::vector<DiffInfo>::iterator cur = available_patches.begin(); for (; cur != available_patches.end(); ++cur) { - if (cur->file != filename || unlikely(cur->result_size != size)) + if (cur->file != filename) continue; cur->result_hashes.push_back(HashString(*type, hash)); break; @@ -601,8 +1716,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile) /*{{{*/ DiffInfo next; next.file = filename; next.result_hashes.push_back(HashString(*type, hash)); - next.result_size = size; - next.patch_size = 0; + next.result_hashes.FileSize(size); available_patches.push_back(next); } else @@ -650,10 +1764,9 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile) /*{{{*/ { if (cur->file != filename) continue; - if (unlikely(cur->patch_size != 0 && cur->patch_size != size)) - continue; + if (cur->patch_hashes.empty()) + cur->patch_hashes.FileSize(size); cur->patch_hashes.push_back(HashString(*type, hash)); - cur->patch_size = size; break; } if (cur != available_patches.end()) @@ -665,6 +1778,48 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile) /*{{{*/ } } + for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type) + { + std::string tagname = *type; + tagname.append("-Download"); + std::string const tmp = Tags.FindS(tagname.c_str()); + if (tmp.empty() == true) + continue; + + string hash, filename; + unsigned long long size; + std::stringstream ss(tmp); + + // FIXME: all of pdiff supports only .gz compressed patches + while (ss >> hash >> size >> filename) + { + if (unlikely(hash.empty() == true || filename.empty() == true)) + continue; + if (unlikely(APT::String::Endswith(filename, ".gz") == false)) + continue; + filename.erase(filename.length() - 3); + + // see if we have a record for this file already + std::vector<DiffInfo>::iterator cur = available_patches.begin(); + for (; cur != available_patches.end(); ++cur) + { + if (cur->file != filename) + continue; + if (cur->download_hashes.empty()) + cur->download_hashes.FileSize(size); + cur->download_hashes.push_back(HashString(*type, hash)); + break; + } + if (cur != available_patches.end()) + continue; + if (Debug == true) + std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": File " << filename + << " wasn't in the list for the first parsed hash! (download)" << std::endl; + break; + } + } + + bool foundStart = false; for (std::vector<DiffInfo>::iterator cur = available_patches.begin(); cur != available_patches.end(); ++cur) @@ -700,7 +1855,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile) /*{{{*/ unsigned long long patchesSize = 0; for (std::vector<DiffInfo>::const_iterator cur = available_patches.begin(); cur != available_patches.end(); ++cur) - patchesSize += cur->patch_size; + patchesSize += cur->patch_hashes.FileSize(); unsigned long long const sizeLimit = ServerSize * _config->FindI("Acquire::PDiffs::SizeLimit", 100); if (sizeLimit > 0 && (sizeLimit/100) < patchesSize) { @@ -729,18 +1884,13 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile) /*{{{*/ } if (pdiff_merge == false) - { - new pkgAcqIndexDiffs(Owner, TransactionManager, Target, ExpectedHashes, - MetaIndexParser, available_patches); - } + 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, - ExpectedHashes, - MetaIndexParser, available_patches[i], diffs); } @@ -751,7 +1901,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile) /*{{{*/ return true; } /*}}}*/ -void pkgAcqDiffIndex::Failed(string Message,pkgAcquire::MethodConfig * Cnf)/*{{{*/ +void pkgAcqDiffIndex::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf)/*{{{*/ { Item::Failed(Message,Cnf); Status = StatDone; @@ -760,49 +1910,16 @@ void pkgAcqDiffIndex::Failed(string Message,pkgAcquire::MethodConfig * Cnf)/*{{{ std::clog << "pkgAcqDiffIndex failed: " << Desc.URI << " with " << Message << std::endl << "Falling back to normal index file acquire" << std::endl; - new pkgAcqIndex(Owner, TransactionManager, Target, ExpectedHashes, MetaIndexParser); -} - /*}}}*/ -bool pkgAcqDiffIndex::TransactionState(TransactionStates const state) /*{{{*/ -{ - if (pkgAcquire::Item::TransactionState(state) == false) - return false; - - switch (state) - { - case TransactionCommit: - break; - case TransactionAbort: - std::string const Partial = GetPartialFileNameFromURI(RealURI); - unlink(Partial.c_str()); - break; - } - - return true; + new pkgAcqIndex(Owner, TransactionManager, Target); } /*}}}*/ -void pkgAcqDiffIndex::Done(string Message,unsigned long long Size,HashStringList const &Hashes, /*{{{*/ - pkgAcquire::MethodConfig *Cnf) +void pkgAcqDiffIndex::Done(string const &Message,HashStringList const &Hashes, /*{{{*/ + pkgAcquire::MethodConfig const * const Cnf) { if(Debug) std::clog << "pkgAcqDiffIndex::Done(): " << Desc.URI << std::endl; - Item::Done(Message, Size, Hashes, Cnf); - - // verify the index target - if(Target && Target->MetaKey != "" && MetaIndexParser && Hashes.usable()) - { - std::string IndexMetaKey = Target->MetaKey + ".diff/Index"; - indexRecords::checkSum *Record = MetaIndexParser->Lookup(IndexMetaKey); - if(Record && Record->Hashes.usable() && Hashes != Record->Hashes) - { - RenameOnError(HashSumMismatch); - printHashSumComparision(RealURI, Record->Hashes, Hashes); - Failed(Message, Cnf); - return; - } - - } + Item::Done(Message, Hashes, Cnf); string const FinalFile = GetFinalFilename(); if(StringToBool(LookupTag(Message,"IMS-Hit"),false)) @@ -826,39 +1943,42 @@ void pkgAcqDiffIndex::Done(string Message,unsigned long long Size,HashStringList return; } /*}}}*/ +pkgAcqDiffIndex::~pkgAcqDiffIndex() +{ + if (diffs != NULL) + delete diffs; +} + // AcqIndexDiffs::AcqIndexDiffs - Constructor /*{{{*/ // --------------------------------------------------------------------- /* The package diff is added to the queue. one object is constructed * for each diff and the index */ -pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire *Owner, - pkgAcqMetaBase *TransactionManager, - struct IndexTarget const * const Target, - HashStringList const &ExpectedHashes, - indexRecords *MetaIndexParser, - vector<DiffInfo> diffs) - : pkgAcqBaseIndex(Owner, TransactionManager, Target, ExpectedHashes, MetaIndexParser), +pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire * const Owner, + pkgAcqMetaClearSig * const TransactionManager, + IndexTarget const &Target, + vector<DiffInfo> const &diffs) + : pkgAcqBaseIndex(Owner, TransactionManager, Target), d(NULL), available_patches(diffs) { - DestFile = GetPartialFileNameFromURI(Target->URI); + DestFile = GetPartialFileNameFromURI(Target.URI); Debug = _config->FindB("Debug::pkgAcquire::Diffs",false); - RealURI = Target->URI; 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(RealURI); + std::string const PartialFile = GetPartialFileNameFromURI(Target.URI); if (RealFileExists(PartialFile) == false) { if (symlink(GetFinalFilename().c_str(), PartialFile.c_str()) != 0) @@ -874,7 +1994,7 @@ pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire *Owner, } } /*}}}*/ -void pkgAcqIndexDiffs::Failed(string Message,pkgAcquire::MethodConfig * Cnf)/*{{{*/ +void pkgAcqIndexDiffs::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf)/*{{{*/ { Item::Failed(Message,Cnf); Status = StatDone; @@ -882,9 +2002,12 @@ void pkgAcqIndexDiffs::Failed(string Message,pkgAcquire::MethodConfig * Cnf)/*{{ 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); - new pkgAcqIndex(Owner, TransactionManager, Target, ExpectedHashes, MetaIndexParser); + std::string const patchname = GetDiffsPatchFileName(DestFile); + if (RealFileExists(patchname)) + rename(patchname.c_str(), std::string(patchname + ".FAILED").c_str()); + new pkgAcqIndex(Owner, TransactionManager, Target); Finish(); } /*}}}*/ @@ -898,15 +2021,8 @@ void pkgAcqIndexDiffs::Finish(bool allDone) // we restore the original name, this is required, otherwise // the file will be cleaned - if(allDone) + if(allDone) { - if(HashSums().usable() && !HashSums().VerifyFile(DestFile)) - { - RenameOnError(HashSumMismatch); - Dequeue(); - return; - } - TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename()); // this is for the "real" finish @@ -929,7 +2045,7 @@ void pkgAcqIndexDiffs::Finish(bool allDone) bool pkgAcqIndexDiffs::QueueNextDiff() /*{{{*/ { // calc sha1 of the just patched file - std::string const FinalFile = GetPartialFileNameFromURI(RealURI); + std::string const FinalFile = GetPartialFileNameFromURI(Target.URI); if(!FileExists(FinalFile)) { @@ -945,7 +2061,8 @@ bool pkgAcqIndexDiffs::QueueNextDiff() /*{{{*/ if(Debug) std::clog << "QueueNextDiff: " << FinalFile << " (" << LocalHashes.find(NULL)->toStr() << ")" << std::endl; - if (unlikely(LocalHashes.usable() == false || ExpectedHashes.usable() == false)) + HashStringList const TargetFileHashes = GetExpectedHashesFor(Target.MetaKey); + if (unlikely(LocalHashes.usable() == false || TargetFileHashes.usable() == false)) { Failed("Local/Expected hashes are not usable", NULL); return false; @@ -953,7 +2070,7 @@ bool pkgAcqIndexDiffs::QueueNextDiff() /*{{{*/ // final file reached before all patches are applied - if(LocalHashes == ExpectedHashes) + if(LocalHashes == TargetFileHashes) { Finish(true); return true; @@ -978,9 +2095,9 @@ bool pkgAcqIndexDiffs::QueueNextDiff() /*{{{*/ } // queue the right diff - Desc.URI = RealURI + ".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(RealURI + ".diff/" + available_patches[0].file); + DestFile = GetPartialFileNameFromURI(Target.URI + ".diff/" + available_patches[0].file); if(Debug) std::clog << "pkgAcqIndexDiffs::QueueNextDiff(): " << Desc.URI << std::endl; @@ -990,36 +2107,21 @@ bool pkgAcqIndexDiffs::QueueNextDiff() /*{{{*/ return true; } /*}}}*/ -void pkgAcqIndexDiffs::Done(string Message,unsigned long long Size, HashStringList const &Hashes, /*{{{*/ - pkgAcquire::MethodConfig *Cnf) +void pkgAcqIndexDiffs::Done(string const &Message, HashStringList const &Hashes, /*{{{*/ + pkgAcquire::MethodConfig const * const Cnf) { if(Debug) std::clog << "pkgAcqIndexDiffs::Done(): " << Desc.URI << std::endl; - Item::Done(Message, Size, Hashes, Cnf); + Item::Done(Message, Hashes, Cnf); - // FIXME: verify this download too before feeding it to rred - std::string const FinalFile = GetPartialFileNameFromURI(RealURI); + std::string const FinalFile = GetPartialFileNameFromURI(Target.URI); + std::string const PatchFile = GetDiffsPatchFileName(FinalFile); // success in downloading a diff, enter ApplyDiff state if(State == StateFetchDiff) { - FileFd fd(DestFile, FileFd::ReadOnly, FileFd::Gzip); - class Hashes LocalHashesCalc; - LocalHashesCalc.AddFD(fd); - HashStringList const LocalHashes = LocalHashesCalc.GetHashStringList(); - - if (fd.Size() != available_patches[0].patch_size || - available_patches[0].patch_hashes != LocalHashes) - { - // patchfiles are dated, so bad indicates a bad download, so kill it - unlink(DestFile.c_str()); - Failed("Patch has Size/Hashsum mismatch", NULL); - return; - } - - // rred excepts the patch as $FinalFile.ed - Rename(DestFile,FinalFile+".ed"); + Rename(DestFile, PatchFile); if(Debug) std::clog << "Sending to rred method: " << FinalFile << std::endl; @@ -1030,18 +2132,17 @@ void pkgAcqIndexDiffs::Done(string Message,unsigned long long Size, HashStringLi QueueURI(Desc); SetActiveSubprocess("rred"); return; - } - + } // success in download/apply a diff, queue next (if needed) if(State == StateApplyDiff) { // remove the just applied patch available_patches.erase(available_patches.begin()); - unlink((FinalFile + ".ed").c_str()); + unlink(PatchFile.c_str()); // move into place - if(Debug) + if(Debug) { std::clog << "Moving patched file in place: " << std::endl << DestFile << " -> " << FinalFile << std::endl; @@ -1052,7 +2153,6 @@ void pkgAcqIndexDiffs::Done(string Message,unsigned long long Size, HashStringLi // see if there is more to download if(available_patches.empty() == false) { new pkgAcqIndexDiffs(Owner, TransactionManager, Target, - ExpectedHashes, MetaIndexParser, available_patches); return Finish(); } else @@ -1062,28 +2162,39 @@ void pkgAcqIndexDiffs::Done(string Message,unsigned long long Size, HashStringLi } } /*}}}*/ +std::string pkgAcqIndexDiffs::Custom600Headers() const /*{{{*/ +{ + if(State != StateApplyDiff) + return pkgAcqBaseIndex::Custom600Headers(); + std::ostringstream patchhashes; + HashStringList const ExpectedHashes = available_patches[0].patch_hashes; + for (HashStringList::const_iterator hs = ExpectedHashes.begin(); hs != ExpectedHashes.end(); ++hs) + patchhashes << "\nPatch-0-" << hs->HashType() << "-Hash: " << hs->HashValue(); + patchhashes << pkgAcqBaseIndex::Custom600Headers(); + return patchhashes.str(); +} + /*}}}*/ +pkgAcqIndexDiffs::~pkgAcqIndexDiffs() {} + // AcqIndexMergeDiffs::AcqIndexMergeDiffs - Constructor /*{{{*/ -pkgAcqIndexMergeDiffs::pkgAcqIndexMergeDiffs(pkgAcquire *Owner, - pkgAcqMetaBase *TransactionManager, - struct IndexTarget const * const Target, - HashStringList const &ExpectedHashes, - indexRecords *MetaIndexParser, +pkgAcqIndexMergeDiffs::pkgAcqIndexMergeDiffs(pkgAcquire * const Owner, + pkgAcqMetaClearSig * const TransactionManager, + IndexTarget const &Target, DiffInfo const &patch, std::vector<pkgAcqIndexMergeDiffs*> const * const allPatches) - : pkgAcqBaseIndex(Owner, TransactionManager, Target, ExpectedHashes, MetaIndexParser), + : pkgAcqBaseIndex(Owner, TransactionManager, Target), d(NULL), patch(patch), allPatches(allPatches), State(StateFetchDiff) { Debug = _config->FindB("Debug::pkgAcquire::Diffs",false); - RealURI = Target->URI; Desc.Owner = this; - Description = Target->Description; - Desc.ShortDesc = Target->ShortDesc; + Description = Target.Description; + Desc.ShortDesc = Target.ShortDesc; - Desc.URI = RealURI + ".diff/" + patch.file + ".gz"; + Desc.URI = Target.URI + ".diff/" + patch.file + ".gz"; Desc.Description = Description + " " + patch.file + string(".pdiff"); - DestFile = GetPartialFileNameFromURI(RealURI + ".diff/" + patch.file); + DestFile = GetPartialFileNameFromURI(Target.URI + ".diff/" + patch.file); if(Debug) std::clog << "pkgAcqIndexMergeDiffs: " << Desc.URI << std::endl; @@ -1091,7 +2202,7 @@ pkgAcqIndexMergeDiffs::pkgAcqIndexMergeDiffs(pkgAcquire *Owner, QueueURI(Desc); } /*}}}*/ -void pkgAcqIndexMergeDiffs::Failed(string Message,pkgAcquire::MethodConfig * Cnf)/*{{{*/ +void pkgAcqIndexMergeDiffs::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf)/*{{{*/ { if(Debug) std::clog << "pkgAcqIndexMergeDiffs failed: " << Desc.URI << " with " << Message << std::endl; @@ -1110,39 +2221,26 @@ void pkgAcqIndexMergeDiffs::Failed(string Message,pkgAcquire::MethodConfig * Cnf 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); - new pkgAcqIndex(Owner, TransactionManager, Target, ExpectedHashes, MetaIndexParser); + std::string const patchname = GetMergeDiffsPatchFileName(DestFile, patch.file); + if (RealFileExists(patchname)) + rename(patchname.c_str(), std::string(patchname + ".FAILED").c_str()); + new pkgAcqIndex(Owner, TransactionManager, Target); } /*}}}*/ -void pkgAcqIndexMergeDiffs::Done(string Message,unsigned long long Size,HashStringList const &Hashes, /*{{{*/ - pkgAcquire::MethodConfig *Cnf) +void pkgAcqIndexMergeDiffs::Done(string const &Message, HashStringList const &Hashes, /*{{{*/ + pkgAcquire::MethodConfig const * const Cnf) { if(Debug) std::clog << "pkgAcqIndexMergeDiffs::Done(): " << Desc.URI << std::endl; - Item::Done(Message,Size,Hashes,Cnf); - - // FIXME: verify download before feeding it to rred - string const FinalFile = GetPartialFileNameFromURI(RealURI); + Item::Done(Message, Hashes, Cnf); + string const FinalFile = GetPartialFileNameFromURI(Target.URI); if (State == StateFetchDiff) { - FileFd fd(DestFile, FileFd::ReadOnly, FileFd::Gzip); - class Hashes LocalHashesCalc; - LocalHashesCalc.AddFD(fd); - HashStringList const LocalHashes = LocalHashesCalc.GetHashStringList(); - - if (fd.Size() != patch.patch_size || patch.patch_hashes != LocalHashes) - { - // patchfiles are dated, so bad indicates a bad download, so kill it - unlink(DestFile.c_str()); - Failed("Patch has Size/Hashsum mismatch", NULL); - return; - } - - // rred expects the patch as $FinalFile.ed.$patchname.gz - Rename(DestFile, FinalFile + ".ed." + patch.file + ".gz"); + Rename(DestFile, GetMergeDiffsPatchFileName(FinalFile, patch.file)); // check if this is the last completed diff State = StateDoneDiff; @@ -1177,13 +2275,6 @@ void pkgAcqIndexMergeDiffs::Done(string Message,unsigned long long Size,HashStri // success in download/apply all diffs, clean up else if (State == StateApplyDiff) { - // see if we really got the expected file - if(ExpectedHashes.usable() && ExpectedHashes != Hashes) - { - RenameOnError(HashSumMismatch); - return; - } - // move the result into place std::string const Final = GetFinalFilename(); if(Debug) @@ -1197,8 +2288,8 @@ void pkgAcqIndexMergeDiffs::Done(string Message,unsigned long long Size,HashStri for (std::vector<pkgAcqIndexMergeDiffs *>::const_iterator I = allPatches->begin(); I != allPatches->end(); ++I) { - std::string const PartialFile = GetPartialFileNameFromURI(RealURI); - std::string patch = PartialFile + ".ed." + (*I)->patch.file + ".gz"; + std::string const PartialFile = GetPartialFileNameFromURI(Target.URI); + std::string const patch = GetMergeDiffsPatchFileName(PartialFile, (*I)->patch.file); unlink(patch.c_str()); } unlink(FinalFile.c_str()); @@ -1210,71 +2301,35 @@ void pkgAcqIndexMergeDiffs::Done(string Message,unsigned long long Size,HashStri } } /*}}}*/ -// AcqBaseIndex - Constructor /*{{{*/ -pkgAcqBaseIndex::pkgAcqBaseIndex(pkgAcquire *Owner, - pkgAcqMetaBase *TransactionManager, - struct IndexTarget const * const Target, - HashStringList const &ExpectedHashes, - indexRecords *MetaIndexParser) -: Item(Owner, ExpectedHashes, TransactionManager), Target(Target), - MetaIndexParser(MetaIndexParser) -{ -} - /*}}}*/ -// AcqBaseIndex::VerifyHashByMetaKey - verify hash for the given metakey /*{{{*/ -bool pkgAcqBaseIndex::VerifyHashByMetaKey(HashStringList const &Hashes) +std::string pkgAcqIndexMergeDiffs::Custom600Headers() const /*{{{*/ { - if(MetaKey != "" && Hashes.usable()) + if(State != StateApplyDiff) + return pkgAcqBaseIndex::Custom600Headers(); + std::ostringstream patchhashes; + unsigned int seen_patches = 0; + for (std::vector<pkgAcqIndexMergeDiffs *>::const_iterator I = allPatches->begin(); + I != allPatches->end(); ++I) { - indexRecords::checkSum *Record = MetaIndexParser->Lookup(MetaKey); - if(Record && Record->Hashes.usable() && Hashes != Record->Hashes) - { - printHashSumComparision(RealURI, Record->Hashes, Hashes); - return false; - } + HashStringList const ExpectedHashes = (*I)->patch.patch_hashes; + for (HashStringList::const_iterator hs = ExpectedHashes.begin(); hs != ExpectedHashes.end(); ++hs) + patchhashes << "\nPatch-" << seen_patches << "-" << hs->HashType() << "-Hash: " << hs->HashValue(); + ++seen_patches; } - return true; + patchhashes << pkgAcqBaseIndex::Custom600Headers(); + return patchhashes.str(); } /*}}}*/ -// AcqBaseIndex::GetFinalFilename - Return the full final file path /*{{{*/ -std::string pkgAcqBaseIndex::GetFinalFilename() const -{ - return GetFinalFileNameFromURI(RealURI); -} - /*}}}*/ -// AcqIndex::AcqIndex - Constructor /*{{{*/ -// --------------------------------------------------------------------- -/* The package file is added to the queue and a second class is - instantiated to fetch the revision file */ -pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner, - string URI,string URIDesc,string ShortDesc, - HashStringList const &ExpectedHash) - : pkgAcqBaseIndex(Owner, 0, NULL, ExpectedHash, NULL) -{ - RealURI = URI; - - AutoSelectCompression(); - Init(URI, URIDesc, ShortDesc); +pkgAcqIndexMergeDiffs::~pkgAcqIndexMergeDiffs() {} - if(_config->FindB("Debug::Acquire::Transaction", false) == true) - std::clog << "New pkgIndex with TransactionManager " - << TransactionManager << std::endl; -} - /*}}}*/ // AcqIndex::AcqIndex - Constructor /*{{{*/ -pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner, - pkgAcqMetaBase *TransactionManager, - IndexTarget const *Target, - HashStringList const &ExpectedHash, - indexRecords *MetaIndexParser) - : pkgAcqBaseIndex(Owner, TransactionManager, Target, ExpectedHash, - MetaIndexParser) +pkgAcqIndex::pkgAcqIndex(pkgAcquire * const Owner, + pkgAcqMetaClearSig * const TransactionManager, + IndexTarget const &Target) + : pkgAcqBaseIndex(Owner, TransactionManager, Target), d(NULL), Stage(STAGE_DOWNLOAD) { - RealURI = Target->URI; - // 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 " @@ -1286,14 +2341,14 @@ void pkgAcqIndex::AutoSelectCompression() { std::vector<std::string> types = APT::Configuration::getCompressionTypes(); CompressionExtensions = ""; - if (ExpectedHashes.usable()) + 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" || - MetaIndexParser->Exists(CompressedMetaKey) == true) + TransactionManager->MetaIndexParser->Exists(CompressedMetaKey) == true) CompressionExtensions.append(*t).append(" "); } } @@ -1314,30 +2369,32 @@ void pkgAcqIndex::Init(string const &URI, string const &URIDesc, DestFile = GetPartialFileNameFromURI(URI); - CurrentCompressionExtension = CompressionExtensions.substr(0, CompressionExtensions.find(' ')); + size_t const nextExt = CompressionExtensions.find(' '); + if (nextExt == std::string::npos) + { + CurrentCompressionExtension = CompressionExtensions; + CompressionExtensions.clear(); + } + else + { + CurrentCompressionExtension = CompressionExtensions.substr(0, nextExt); + CompressionExtensions = CompressionExtensions.substr(nextExt+1); + } + if (CurrentCompressionExtension == "uncompressed") { Desc.URI = URI; - if(Target) - MetaKey = string(Target->MetaKey); } + else if (unlikely(CurrentCompressionExtension.empty())) + return; else { Desc.URI = URI + '.' + CurrentCompressionExtension; DestFile = DestFile + '.' + CurrentCompressionExtension; - if(Target) - MetaKey = string(Target->MetaKey) + '.' + CurrentCompressionExtension; } - // load the filesize - if(MetaIndexParser) - { - indexRecords::checkSum *Record = MetaIndexParser->Lookup(MetaKey); - if(Record) - FileSize = Record->Size; - - InitByHashIfNeeded(MetaKey); - } + if(TransactionManager->MetaIndexParser != NULL) + InitByHashIfNeeded(); Desc.Description = URIDesc; Desc.Owner = this; @@ -1347,7 +2404,7 @@ void pkgAcqIndex::Init(string const &URI, string const &URIDesc, } /*}}}*/ // AcqIndex::AdjustForByHash - modify URI for by-hash support /*{{{*/ -void pkgAcqIndex::InitByHashIfNeeded(const std::string MetaKey) +void pkgAcqIndex::InitByHashIfNeeded() { // TODO: // - (maybe?) add support for by-hash into the sources.list as flag @@ -1355,15 +2412,15 @@ void pkgAcqIndex::InitByHashIfNeeded(const std::string MetaKey) 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()) + TransactionManager->MetaIndexParser->GetSupportsAcquireByHash()) { - indexRecords::checkSum *Record = MetaIndexParser->Lookup(MetaKey); - if(Record) + HashStringList const Hashes = GetExpectedHashes(); + if(Hashes.usable()) { // 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("/"); + HashString const * const TargetHash = Hashes.find(""); + std::string const ByHash = "/by-hash/" + TargetHash->HashType() + "/" + TargetHash->HashValue(); + size_t const trailing_slash = Desc.URI.find_last_of("/"); Desc.URI = Desc.URI.replace( trailing_slash, Desc.URI.substr(trailing_slash+1).size()+1, @@ -1371,7 +2428,7 @@ void pkgAcqIndex::InitByHashIfNeeded(const std::string MetaKey) } else { _error->Warning( "Fetching ByHash requested but can not find record for %s", - MetaKey.c_str()); + GetMetaKey().c_str()); } } } @@ -1379,11 +2436,7 @@ void pkgAcqIndex::InitByHashIfNeeded(const std::string MetaKey) // AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/ // --------------------------------------------------------------------- /* The only header we use is the last-modified header. */ -#if APT_PKG_ABI >= 413 string pkgAcqIndex::Custom600Headers() const -#else -string pkgAcqIndex::Custom600Headers() -#endif { string Final = GetFinalFilename(); @@ -1392,71 +2445,40 @@ string pkgAcqIndex::Custom600Headers() 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; } /*}}}*/ -// pkgAcqIndex::Failed - getting the indexfile failed /*{{{*/ -void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf) +// AcqIndex::Failed - getting the indexfile failed /*{{{*/ +void pkgAcqIndex::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf) { Item::Failed(Message,Cnf); - size_t const nextExt = CompressionExtensions.find(' '); - if (nextExt != std::string::npos) + // authorisation matches will not be fixed by other compression types + if (Status != StatAuthError) { - CompressionExtensions = CompressionExtensions.substr(nextExt+1); - Init(RealURI, Desc.Description, Desc.ShortDesc); - Status = StatIdle; - return; + if (CompressionExtensions.empty() == false) + { + Init(Target.URI, Desc.Description, Desc.ShortDesc); + Status = StatIdle; + return; + } } - Item::Failed(Message,Cnf); - - if(Target->IsOptional() && ExpectedHashes.empty() && Stage == STAGE_DOWNLOAD) + if(Target.IsOptional && GetExpectedHashes().empty() && Stage == STAGE_DOWNLOAD) Status = StatDone; else TransactionManager->AbortTransaction(); } /*}}}*/ -bool pkgAcqIndex::TransactionState(TransactionStates const state) /*{{{*/ -{ - if (pkgAcquire::Item::TransactionState(state) == false) - return false; - - switch (state) - { - case TransactionAbort: - if (Stage == STAGE_DECOMPRESS_AND_VERIFY) - { - // keep the compressed file, but drop the decompressed - EraseFileName.clear(); - if (PartialFile.empty() == false && flExtension(PartialFile) == "decomp") - unlink(PartialFile.c_str()); - } - break; - case TransactionCommit: - if (EraseFileName.empty() == false) - unlink(EraseFileName.c_str()); - break; - } - return true; -} - /*}}}*/ -// pkgAcqIndex::GetFinalFilename - Return the full final file path /*{{{*/ -std::string pkgAcqIndex::GetFinalFilename() const -{ - std::string const FinalFile = GetFinalFileNameFromURI(RealURI); - return GetCompressedFileName(RealURI, FinalFile, CurrentCompressionExtension); -} - /*}}}*/ // AcqIndex::ReverifyAfterIMS - Reverify index after an ims-hit /*{{{*/ void pkgAcqIndex::ReverifyAfterIMS() { // update destfile to *not* include the compression extension when doing // a reverify (as its uncompressed on disk already) - DestFile = GetCompressedFileName(RealURI, GetPartialFileNameFromURI(RealURI), CurrentCompressionExtension); + DestFile = GetCompressedFileName(Target, GetPartialFileNameFromURI(Target.URI), CurrentCompressionExtension); // copy FinalFile into partial/ so that we check the hash again string FinalFile = GetFinalFilename(); @@ -1465,33 +2487,6 @@ void pkgAcqIndex::ReverifyAfterIMS() QueueURI(Desc); } /*}}}*/ -// AcqIndex::ValidateFile - Validate the content of the downloaded file /*{{{*/ -bool pkgAcqIndex::ValidateFile(const std::string &FileName) -{ - // FIXME: this can go away once we only ever download stuff that - // has a valid hash and we never do GET based probing - // FIXME2: this also leaks debian-isms into the code and should go therefore - - /* Always validate the index file for correctness (all indexes must - * have a Package field) (LP: #346386) (Closes: #627642) - */ - FileFd fd(FileName, FileFd::ReadOnly, FileFd::Extension); - // Only test for correctness if the content of the file is not empty - // (empty is ok) - if (fd.Size() > 0) - { - pkgTagSection sec; - pkgTagFile tag(&fd); - - // all our current indexes have a field 'Package' in each section - if (_error->PendingError() == true || - tag.Step(sec) == false || - sec.Exists("Package") == false) - return false; - } - return true; -} - /*}}}*/ // AcqIndex::Done - Finished a fetch /*{{{*/ // --------------------------------------------------------------------- /* This goes through a number of states.. On the initial fetch the @@ -1499,12 +2494,11 @@ bool pkgAcqIndex::ValidateFile(const std::string &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 compressed uri. */ -void pkgAcqIndex::Done(string Message, - unsigned long long Size, +void pkgAcqIndex::Done(string const &Message, HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cfg) + pkgAcquire::MethodConfig const * const Cfg) { - Item::Done(Message,Size,Hashes,Cfg); + Item::Done(Message,Hashes,Cfg); switch(Stage) { @@ -1518,23 +2512,13 @@ void pkgAcqIndex::Done(string Message, } /*}}}*/ // AcqIndex::StageDownloadDone - Queue for decompress and verify /*{{{*/ -void pkgAcqIndex::StageDownloadDone(string Message, - HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cfg) +void pkgAcqIndex::StageDownloadDone(string const &Message, HashStringList const &, + pkgAcquire::MethodConfig const * const) { - // First check if the calculcated Hash of the (compressed) downloaded - // file matches the hash we have in the MetaIndexRecords for this file - if(VerifyHashByMetaKey(Hashes) == false) - { - RenameOnError(HashSumMismatch); - Failed(Message, Cfg); - return; - } - 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; @@ -1545,17 +2529,11 @@ void pkgAcqIndex::StageDownloadDone(string Message, 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; @@ -1570,10 +2548,10 @@ void pkgAcqIndex::StageDownloadDone(string Message, 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(RealURI + '.' + CurrentCompressionExtension); + DestFile = GetPartialFileNameFromURI(Target.URI + '.' + CurrentCompressionExtension); EraseFileName = ""; Stage = STAGE_DECOMPRESS_AND_VERIFY; Desc.URI = "copy:" + FileName; @@ -1602,879 +2580,28 @@ void pkgAcqIndex::StageDownloadDone(string Message, SetActiveSubprocess(decompProg); } /*}}}*/ -// pkgAcqIndex::StageDecompressDone - Final verification /*{{{*/ -void pkgAcqIndex::StageDecompressDone(string Message, - HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cfg) +// AcqIndex::StageDecompressDone - Final verification /*{{{*/ +void pkgAcqIndex::StageDecompressDone(string const &, + HashStringList const &, + pkgAcquire::MethodConfig const * const) { - if (ExpectedHashes.usable() && ExpectedHashes != Hashes) - { - Desc.URI = RealURI; - RenameOnError(HashSumMismatch); - printHashSumComparision(RealURI, ExpectedHashes, Hashes); - Failed(Message, Cfg); - return; - } - - if(!ValidateFile(DestFile)) - { - RenameOnError(InvalidFormat); - Failed(Message, Cfg); - return; - } - // Done, queue for rename on transaction finished TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename()); - return; } /*}}}*/ -// AcqMetaBase - Constructor /*{{{*/ -pkgAcqMetaBase::pkgAcqMetaBase(pkgAcquire *Owner, - const std::vector<IndexTarget*>* IndexTargets, - indexRecords* MetaIndexParser, - std::string const &RealURI, - HashStringList const &ExpectedHashes, - pkgAcqMetaBase *TransactionManager) -: Item(Owner, ExpectedHashes, TransactionManager), - MetaIndexParser(MetaIndexParser), LastMetaIndexParser(NULL), IndexTargets(IndexTargets), - AuthPass(false), RealURI(RealURI), IMSHit(false) -{ -} - /*}}}*/ -// AcqMetaBase::Add - Add a item to the current Transaction /*{{{*/ -void pkgAcqMetaBase::Add(Item *I) -{ - Transaction.push_back(I); -} - /*}}}*/ -// AcqMetaBase::AbortTransaction - Abort the current Transaction /*{{{*/ -void pkgAcqMetaBase::AbortTransaction() -{ - if(_config->FindB("Debug::Acquire::Transaction", false) == true) - std::clog << "AbortTransaction: " << TransactionManager << std::endl; +pkgAcqIndex::~pkgAcqIndex() {} - // ensure the toplevel is in error state too - for (std::vector<Item*>::iterator I = Transaction.begin(); - I != Transaction.end(); ++I) - { - (*I)->TransactionState(TransactionAbort); - } - Transaction.clear(); -} - /*}}}*/ -// AcqMetaBase::TransactionHasError - Check for errors in Transaction /*{{{*/ -bool pkgAcqMetaBase::TransactionHasError() -{ - for (pkgAcquire::ItemIterator I = Transaction.begin(); - I != Transaction.end(); ++I) - { - switch((*I)->Status) { - case StatDone: break; - case StatIdle: break; - case StatAuthError: return true; - case StatError: return true; - case StatTransientNetworkError: return true; - case StatFetching: break; - } - } - return false; -} - /*}}}*/ -// AcqMetaBase::CommitTransaction - Commit a transaction /*{{{*/ -void pkgAcqMetaBase::CommitTransaction() -{ - if(_config->FindB("Debug::Acquire::Transaction", false) == true) - std::clog << "CommitTransaction: " << this << std::endl; - - // move new files into place *and* remove files that are not - // part of the transaction but are still on disk - for (std::vector<Item*>::iterator I = Transaction.begin(); - I != Transaction.end(); ++I) - { - (*I)->TransactionState(TransactionCommit); - } - Transaction.clear(); -} - /*}}}*/ -bool pkgAcqMetaBase::TransactionState(TransactionStates const state) /*{{{*/ -{ - // Do not remove InRelease on IMSHit of Release.gpg [yes, this is very edgecasey] - if (TransactionManager->IMSHit == false) - return pkgAcquire::Item::TransactionState(state); - return true; -} - /*}}}*/ -// AcqMetaBase::TransactionStageCopy - Stage a file for copying /*{{{*/ -void pkgAcqMetaBase::TransactionStageCopy(Item *I, - const std::string &From, - const std::string &To) -{ - I->PartialFile = From; - I->DestFile = To; -} - /*}}}*/ -// AcqMetaBase::TransactionStageRemoval - Stage a file for removal /*{{{*/ -void pkgAcqMetaBase::TransactionStageRemoval(Item *I, - const std::string &FinalFile) -{ - I->PartialFile = ""; - I->DestFile = FinalFile; -} - /*}}}*/ -// AcqMetaBase::GenerateAuthWarning - Check gpg authentication error /*{{{*/ -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)) - { - 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\n"), - Desc.Description.c_str(), - LookupTag(Message,"Message").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()); - I->Status = StatError; - return true; - } else { - _error->Warning(_("GPG error: %s: %s"), - Desc.Description.c_str(), - LookupTag(Message,"Message").c_str()); - } - // gpgv method failed - ReportMirrorFailure("GPGFailure"); - return false; -} - /*}}}*/ -// AcqMetaSig::AcqMetaSig - Constructor /*{{{*/ -pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner, - pkgAcqMetaBase *TransactionManager, - string const &URI, string const &URIDesc,string const &ShortDesc, - pkgAcqMetaIndex * const MetaIndex) : - pkgAcquire::Item(Owner, HashStringList(), TransactionManager), MetaIndex(MetaIndex), - URIDesc(URIDesc), RealURI(URI) -{ - DestFile = GetPartialFileNameFromURI(URI); - // remove any partial downloaded sig-file in partial/. - // it may confuse proxies and is too small to warrant a - // partial download anyway - unlink(DestFile.c_str()); - - // set the TransactionManager - if(_config->FindB("Debug::Acquire::Transaction", false) == true) - std::clog << "New pkgAcqMetaSig with TransactionManager " - << TransactionManager << std::endl; - - // Create the item - Desc.Description = URIDesc; - Desc.Owner = this; - Desc.ShortDesc = ShortDesc; - Desc.URI = 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 - if (TransactionManager->IMSHit == true && RealFileExists(GetFinalFilename())) - { - Complete = true; - Status = StatDone; - PartialFile = DestFile = GetFinalFilename(); - MetaIndexFileSignature = DestFile; - MetaIndex->QueueForSignatureVerify(this, MetaIndex->DestFile, DestFile); - } - else - QueueURI(Desc); -} - /*}}}*/ -pkgAcqMetaSig::~pkgAcqMetaSig() /*{{{*/ -{ -} - /*}}}*/ -// pkgAcqMetaSig::GetFinalFilename - Return the full final file path /*{{{*/ -std::string pkgAcqMetaSig::GetFinalFilename() const -{ - return GetFinalFileNameFromURI(RealURI); -} - /*}}}*/ -// pkgAcqMetaSig::Done - The signature was downloaded/verified /*{{{*/ -// --------------------------------------------------------------------- -/* The only header we use is the last-modified header. */ -void pkgAcqMetaSig::Done(string Message,unsigned long long Size, - HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cfg) -{ - if (MetaIndexFileSignature.empty() == false) - { - DestFile = MetaIndexFileSignature; - MetaIndexFileSignature.clear(); - } - Item::Done(Message, Size, Hashes, Cfg); - - if(MetaIndex->AuthPass == false) - { - if(MetaIndex->CheckDownloadDone(this, Message, Hashes) == true) - { - // destfile will be modified to point to MetaIndexFile for the - // gpgv method, so we need to save it here - MetaIndexFileSignature = DestFile; - MetaIndex->QueueForSignatureVerify(this, MetaIndex->DestFile, DestFile); - } - return; - } - else if(MetaIndex->CheckAuthDone(Message) == true) - { - if (TransactionManager->IMSHit == false) - { - TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename()); - TransactionManager->TransactionStageCopy(MetaIndex, MetaIndex->DestFile, MetaIndex->GetFinalFilename()); - } - } -} - /*}}}*/ -void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)/*{{{*/ -{ - Item::Failed(Message,Cnf); - - // check if we need to fail at this point - if (MetaIndex->AuthPass == true && MetaIndex->CheckStopAuthentication(this, Message)) - return; - - string const FinalRelease = MetaIndex->GetFinalFilename(); - string const FinalReleasegpg = GetFinalFilename(); - string const FinalInRelease = TransactionManager->GetFinalFilename(); - - if (RealFileExists(FinalReleasegpg) || RealFileExists(FinalInRelease)) - { - std::string downgrade_msg; - strprintf(downgrade_msg, _("The repository '%s' is no longer signed."), - MetaIndex->URIDesc.c_str()); - if(_config->FindB("Acquire::AllowDowngradeToInsecureRepositories")) - { - // meh, the users wants to take risks (we still mark the packages - // from this repository as unauthenticated) - _error->Warning("%s", downgrade_msg.c_str()); - _error->Warning(_("This is normally not allowed, but the option " - "Acquire::AllowDowngradeToInsecureRepositories was " - "given to override it.")); - Status = StatDone; - } else { - _error->Error("%s", downgrade_msg.c_str()); - if (TransactionManager->IMSHit == false) - Rename(MetaIndex->DestFile, MetaIndex->DestFile + ".FAILED"); - Item::Failed("Message: " + downgrade_msg, Cnf); - TransactionManager->AbortTransaction(); - return; - } - } - else - _error->Warning(_("The data from '%s' is not signed. Packages " - "from that repository can not be authenticated."), - MetaIndex->URIDesc.c_str()); - - // ensures that a Release.gpg file in the lists/ is removed by the transaction - TransactionManager->TransactionStageRemoval(this, DestFile); - - // only allow going further if the users explicitely wants it - if(AllowInsecureRepositories(MetaIndex->MetaIndexParser, TransactionManager, this) == true) - { - if (RealFileExists(FinalReleasegpg) || RealFileExists(FinalInRelease)) - { - // open the last Release if we have it - if (TransactionManager->IMSHit == false) - { - MetaIndex->LastMetaIndexParser = new indexRecords; - _error->PushToStack(); - if (RealFileExists(FinalInRelease)) - MetaIndex->LastMetaIndexParser->Load(FinalInRelease); - else - MetaIndex->LastMetaIndexParser->Load(FinalRelease); - // its unlikely to happen, but if what we have is bad ignore it - if (_error->PendingError()) - { - delete MetaIndex->LastMetaIndexParser; - MetaIndex->LastMetaIndexParser = NULL; - } - _error->RevertToStack(); - } - } - - // we parse the indexes here because at this point the user wanted - // a repository that may potentially harm him - MetaIndex->MetaIndexParser->Load(MetaIndex->DestFile); - if (MetaIndex->VerifyVendor(Message) == false) - /* expired Release files are still a problem you need extra force for */; - else - MetaIndex->QueueIndexes(true); - - TransactionManager->TransactionStageCopy(MetaIndex, MetaIndex->DestFile, MetaIndex->GetFinalFilename()); - } - - // FIXME: this is used often (e.g. in pkgAcqIndexTrans) so refactor - if (Cnf->LocalOnly == true || - StringToBool(LookupTag(Message,"Transient-Failure"),false) == false) - { - // Ignore this - Status = StatDone; - } -} - /*}}}*/ -pkgAcqMetaIndex::pkgAcqMetaIndex(pkgAcquire *Owner, /*{{{*/ - pkgAcqMetaBase *TransactionManager, - string URI,string URIDesc,string ShortDesc, - string MetaIndexSigURI,string MetaIndexSigURIDesc, string MetaIndexSigShortDesc, - const vector<IndexTarget*>* IndexTargets, - indexRecords* MetaIndexParser) : - pkgAcqMetaBase(Owner, IndexTargets, MetaIndexParser, URI, HashStringList(), - TransactionManager), - URIDesc(URIDesc), ShortDesc(ShortDesc), - MetaIndexSigURI(MetaIndexSigURI), MetaIndexSigURIDesc(MetaIndexSigURIDesc), - MetaIndexSigShortDesc(MetaIndexSigShortDesc) -{ - if(TransactionManager == NULL) - { - this->TransactionManager = this; - this->TransactionManager->Add(this); - } - - if(_config->FindB("Debug::Acquire::Transaction", false) == true) - std::clog << "New pkgAcqMetaIndex with TransactionManager " - << this->TransactionManager << std::endl; - - - Init(URIDesc, ShortDesc); -} - /*}}}*/ -// pkgAcqMetaIndex::Init - Delayed constructor /*{{{*/ -void pkgAcqMetaIndex::Init(std::string URIDesc, std::string ShortDesc) -{ - DestFile = GetPartialFileNameFromURI(RealURI); - - // Create the item - Desc.Description = URIDesc; - Desc.Owner = this; - Desc.ShortDesc = ShortDesc; - Desc.URI = RealURI; - - // we expect more item - ExpectedAdditionalItems = IndexTargets->size(); - QueueURI(Desc); -} - /*}}}*/ -void pkgAcqMetaIndex::Done(string Message,unsigned long long Size, /*{{{*/ - HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cfg) -{ - Item::Done(Message,Size,Hashes,Cfg); - - if(CheckDownloadDone(this, Message, Hashes)) - { - // 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, - MetaIndexSigURI, MetaIndexSigURIDesc, - MetaIndexSigShortDesc, this); - } -} - /*}}}*/ -bool pkgAcqMetaBase::CheckAuthDone(string Message) /*{{{*/ -{ - // At this point, the gpgv method has succeeded, so there is a - // valid signature from a key in the trusted keyring. We - // perform additional verification of its contents, and use them - // to verify the indexes we are about to download - - if (TransactionManager->IMSHit == false) - { - // open the last (In)Release if we have it - std::string const FinalFile = GetFinalFilename(); - std::string FinalRelease; - std::string FinalInRelease; - if (APT::String::Endswith(FinalFile, "InRelease")) - { - FinalInRelease = FinalFile; - FinalRelease = FinalFile.substr(0, FinalFile.length() - strlen("InRelease")) + "Release"; - } - else - { - FinalInRelease = FinalFile.substr(0, FinalFile.length() - strlen("Release")) + "InRelease"; - FinalRelease = FinalFile; - } - if (RealFileExists(FinalInRelease) || RealFileExists(FinalRelease)) - { - LastMetaIndexParser = new indexRecords; - _error->PushToStack(); - if (RealFileExists(FinalInRelease)) - LastMetaIndexParser->Load(FinalInRelease); - else - LastMetaIndexParser->Load(FinalRelease); - // its unlikely to happen, but if what we have is bad ignore it - if (_error->PendingError()) - { - delete LastMetaIndexParser; - LastMetaIndexParser = NULL; - } - _error->RevertToStack(); - } - } - - if (!MetaIndexParser->Load(DestFile)) - { - Status = StatAuthError; - ErrorText = MetaIndexParser->ErrorText; - return false; - } - - if (!VerifyVendor(Message)) - { - Status = StatAuthError; - return false; - } - - if (_config->FindB("Debug::pkgAcquire::Auth", false)) - std::cerr << "Signature verification succeeded: " - << DestFile << std::endl; - - // Download further indexes with verification - QueueIndexes(true); - - return true; -} - /*}}}*/ -// pkgAcqMetaBase::Custom600Headers - Get header for AcqMetaBase /*{{{*/ -// --------------------------------------------------------------------- -#if APT_PKG_ABI >= 413 -string pkgAcqMetaBase::Custom600Headers() const -#else -string pkgAcqMetaBase::Custom600Headers() -#endif -{ - std::string Header = "\nIndex-File: true"; - std::string MaximumSize; - strprintf(MaximumSize, "\nMaximum-Size: %i", - _config->FindI("Acquire::MaxReleaseFileSize", 10*1000*1000)); - Header += MaximumSize; - - string const FinalFile = GetFinalFilename(); - - struct stat Buf; - if (stat(FinalFile.c_str(),&Buf) == 0) - Header += "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime); - - return Header; -} - /*}}}*/ -// pkgAcqMetaBase::GetFinalFilename - Return the full final file path /*{{{*/ -std::string pkgAcqMetaBase::GetFinalFilename() const -{ - return GetFinalFileNameFromURI(RealURI); -} - /*}}}*/ -// pkgAcqMetaBase::QueueForSignatureVerify /*{{{*/ -void pkgAcqMetaBase::QueueForSignatureVerify(pkgAcquire::Item * const I, std::string const &File, std::string const &Signature) -{ - AuthPass = true; - I->Desc.URI = "gpgv:" + Signature; - I->DestFile = File; - QueueURI(I->Desc); - I->SetActiveSubprocess("gpgv"); -} - /*}}}*/ -// pkgAcqMetaBase::CheckDownloadDone /*{{{*/ -bool pkgAcqMetaBase::CheckDownloadDone(pkgAcquire::Item * const I, const std::string &Message, HashStringList const &Hashes) const -{ - // 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) - { - I->Local = true; - I->Desc.URI = "copy:" + FileName; - I->QueueURI(I->Desc); - return false; - } - - // make sure to verify against the right file on I-M-S hit - bool IMSHit = StringToBool(LookupTag(Message,"IMS-Hit"), false); - if (IMSHit == false && Hashes.usable()) - { - // detect IMS-Hits servers haven't detected by Hash comparison - std::string const FinalFile = I->GetFinalFilename(); - if (RealFileExists(FinalFile) && Hashes.VerifyFile(FinalFile) == true) - { - IMSHit = true; - unlink(I->DestFile.c_str()); - } - } - - if(IMSHit == true) - { - // for simplicity, the transaction manager is always InRelease - // even if it doesn't exist. - if (TransactionManager != NULL) - TransactionManager->IMSHit = true; - I->PartialFile = I->DestFile = I->GetFinalFilename(); - } - - // set Item to complete as the remaining work is all local (verify etc) - I->Complete = true; - - return true; -} - /*}}}*/ -void pkgAcqMetaBase::QueueIndexes(bool verify) /*{{{*/ -{ - // at this point the real Items are loaded in the fetcher - ExpectedAdditionalItems = 0; - - vector <struct IndexTarget*>::const_iterator Target; - for (Target = IndexTargets->begin(); - Target != IndexTargets->end(); - ++Target) - { - HashStringList ExpectedIndexHashes; - const indexRecords::checkSum *Record = MetaIndexParser->Lookup((*Target)->MetaKey); - - // optional target that we do not have in the Release file are - // skipped - if (verify == true && Record == NULL && (*Target)->IsOptional()) - continue; - - // targets without a hash record are a error when verify is required - if (verify == true && Record == NULL) - { - Status = StatAuthError; - strprintf(ErrorText, _("Unable to find expected entry '%s' in Release file (Wrong sources.list entry or malformed file)"), (*Target)->MetaKey.c_str()); - return; - } - - if (Record) - ExpectedIndexHashes = Record->Hashes; - - if (_config->FindB("Debug::pkgAcquire::Auth", false)) - { - 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 == NULL) ? "<NULL>" : Record->MetaKeyFilename) << std::endl; - - } - if (verify == true && ExpectedIndexHashes.empty() == true) - { - Status = StatAuthError; - strprintf(ErrorText, _("Unable to find hash sum for '%s' in Release file"), (*Target)->MetaKey.c_str()); - return; - } - - /* Queue the Index file (Packages, Sources, Translation-$foo - (either diff or full packages files, depending - on the users option) - we also check if the PDiff Index file is listed - in the Meta-Index file. Ideal would be if pkgAcqDiffIndex would test this - 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, TransactionManager, *Target, ExpectedIndexHashes, MetaIndexParser); - else - new pkgAcqIndex(Owner, TransactionManager, *Target, ExpectedIndexHashes, MetaIndexParser); - } -} - /*}}}*/ -bool pkgAcqMetaBase::VerifyVendor(string Message) /*{{{*/ -{ - 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 = MetaIndexParser->GetExpectedDist(); - - if (Transformed == "../project/experimental") - { - Transformed = "experimental"; - } - - pos = Transformed.rfind('/'); - if (pos != string::npos) - { - Transformed = Transformed.substr(0, pos); - } - - if (Transformed == ".") - { - Transformed = ""; - } - - if (_config->FindB("Acquire::Check-Valid-Until", true) == true && - MetaIndexParser->GetValidUntil() > 0) { - time_t const invalid_since = time(NULL) - 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 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."), - RealURI.c_str(), TimeToStr(invalid_since).c_str()); - if (ErrorText.empty()) - ErrorText = errmsg; - return _error->Error("%s", errmsg.c_str()); - } - } - - /* Did we get a file older than what we have? This is a last minute IMS hit and doubles - as a prevention of downgrading us to older (still valid) files */ - if (TransactionManager->IMSHit == false && LastMetaIndexParser != NULL && - LastMetaIndexParser->GetDate() > MetaIndexParser->GetDate()) - { - TransactionManager->IMSHit = true; - unlink(DestFile.c_str()); - PartialFile = DestFile = GetFinalFilename(); - delete MetaIndexParser; - MetaIndexParser = LastMetaIndexParser; - LastMetaIndexParser = NULL; - } - - if (_config->FindB("Debug::pkgAcquire::Auth", false)) - { - std::cerr << "Got Codename: " << MetaIndexParser->GetDist() << std::endl; - std::cerr << "Expecting Dist: " << MetaIndexParser->GetExpectedDist() << std::endl; - std::cerr << "Transformed Dist: " << Transformed << std::endl; - } - - if (MetaIndexParser->CheckDist(Transformed) == false) - { - // This might become fatal one day -// Status = StatAuthError; -// ErrorText = "Conflicting distribution; expected " -// + MetaIndexParser->GetExpectedDist() + " but got " -// + MetaIndexParser->GetDist(); -// return false; - if (!Transformed.empty()) - { - _error->Warning(_("Conflicting distribution: %s (expected %s but got %s)"), - Desc.Description.c_str(), - Transformed.c_str(), - MetaIndexParser->GetDist().c_str()); - } - } - - return true; -} - /*}}}*/ -// pkgAcqMetaIndex::Failed - no Release file present /*{{{*/ -void pkgAcqMetaIndex::Failed(string Message, - pkgAcquire::MethodConfig * Cnf) -{ - pkgAcquire::Item::Failed(Message, Cnf); - Status = StatDone; - - _error->Warning(_("The repository '%s' does not have a Release file. " - "This is deprecated, please contact the owner of the " - "repository."), URIDesc.c_str()); - - // No Release file was present so fall - // back to queueing Packages files without verification - // only allow going further if the users explicitely wants it - if(AllowInsecureRepositories(MetaIndexParser, TransactionManager, this) == true) - { - // Done, queue for rename on transaction finished - if (FileExists(DestFile)) - TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename()); - - // queue without any kind of hashsum support - QueueIndexes(false); - } -} - /*}}}*/ -void pkgAcqMetaIndex::Finished() /*{{{*/ -{ - if(_config->FindB("Debug::Acquire::Transaction", false) == true) - std::clog << "Finished: " << DestFile <<std::endl; - if(TransactionManager != NULL && - TransactionManager->TransactionHasError() == false) - TransactionManager->CommitTransaction(); -} - /*}}}*/ -pkgAcqMetaClearSig::pkgAcqMetaClearSig(pkgAcquire *Owner, /*{{{*/ - 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<IndexTarget*>* IndexTargets, - indexRecords* MetaIndexParser) : - pkgAcqMetaIndex(Owner, NULL, URI, URIDesc, ShortDesc, MetaSigURI, MetaSigURIDesc,MetaSigShortDesc, IndexTargets, MetaIndexParser), - MetaIndexURI(MetaIndexURI), MetaIndexURIDesc(MetaIndexURIDesc), MetaIndexShortDesc(MetaIndexShortDesc), - MetaSigURI(MetaSigURI), MetaSigURIDesc(MetaSigURIDesc), MetaSigShortDesc(MetaSigShortDesc) -{ - // index targets + (worst case:) Release/Release.gpg - ExpectedAdditionalItems = IndexTargets->size() + 2; -} - /*}}}*/ -pkgAcqMetaClearSig::~pkgAcqMetaClearSig() /*{{{*/ -{ -} - /*}}}*/ -// pkgAcqMetaClearSig::Custom600Headers - Insert custom request headers /*{{{*/ -#if APT_PKG_ABI >= 413 -string pkgAcqMetaClearSig::Custom600Headers() const -#else -string pkgAcqMetaClearSig::Custom600Headers() -#endif -{ - string Header = pkgAcqMetaBase::Custom600Headers(); - Header += "\nFail-Ignore: true"; - return Header; -} - /*}}}*/ -// pkgAcqMetaClearSig::Done - We got a file /*{{{*/ -class APT_HIDDEN DummyItem : public pkgAcquire::Item -{ - std::string URI; - public: - virtual std::string DescURI() {return URI;}; - - DummyItem(pkgAcquire *Owner, std::string const &URI) : pkgAcquire::Item(Owner), URI(URI) - { - Status = StatDone; - DestFile = GetFinalFileNameFromURI(URI); - } -}; -void pkgAcqMetaClearSig::Done(std::string Message,unsigned long long Size, - HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cnf) -{ - Item::Done(Message, Size, 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) - QueueForSignatureVerify(this, DestFile, DestFile); - return; - } - else if(CheckAuthDone(Message) == true) - { - if (TransactionManager->IMSHit == false) - TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename()); - else if (RealFileExists(GetFinalFilename()) == false) - { - // 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 DummyItem(Owner, MetaIndexURI); - new DummyItem(Owner, MetaSigURI); - } - } -} - /*}}}*/ -void pkgAcqMetaClearSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /*{{{*/ -{ - Item::Failed(Message, Cnf); - - // we failed, we will not get additional items from this method - ExpectedAdditionalItems = 0; - - if (AuthPass == false) - { - // 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, - MetaIndexURI, MetaIndexURIDesc, MetaIndexShortDesc, - MetaSigURI, MetaSigURIDesc, MetaSigShortDesc, - IndexTargets, MetaIndexParser); - } - else - { - if(CheckStopAuthentication(this, Message)) - return; - - _error->Warning(_("The data from '%s' is not signed. Packages " - "from that repository can not be authenticated."), - URIDesc.c_str()); - - // No Release file was present, or verification failed, so fall - // back to queueing Packages files without verification - // only allow going further if the users explicitely wants it - if(AllowInsecureRepositories(MetaIndexParser, TransactionManager, this) == true) - { - Status = StatDone; - - /* Always move the meta index, even if gpgv failed. This ensures - * that PackageFile objects are correctly filled in */ - if (FileExists(DestFile)) - { - string FinalFile = GetFinalFilename(); - /* InRelease files become Release files, otherwise - * they would be considered as trusted later on */ - RealURI = RealURI.replace(RealURI.rfind("InRelease"), 9, - "Release"); - FinalFile = FinalFile.replace(FinalFile.rfind("InRelease"), 9, - "Release"); - - // Done, queue for rename on transaction finished - TransactionManager->TransactionStageCopy(this, DestFile, FinalFile); - } - QueueIndexes(false); - } - } -} - /*}}}*/ // AcqArchive::AcqArchive - Constructor /*{{{*/ // --------------------------------------------------------------------- /* This just sets up the initial fetch environment and queues the first possibilitiy */ -pkgAcqArchive::pkgAcqArchive(pkgAcquire *Owner,pkgSourceList *Sources, - pkgRecords *Recs,pkgCache::VerIterator const &Version, +pkgAcqArchive::pkgAcqArchive(pkgAcquire * const Owner,pkgSourceList * const Sources, + pkgRecords * const Recs,pkgCache::VerIterator const &Version, string &StoreFilename) : - Item(Owner, HashStringList()), Version(Version), Sources(Sources), Recs(Recs), - StoreFilename(StoreFilename), Vf(Version.FileList()), + Item(Owner), d(NULL), LocalSource(false), Version(Version), Sources(Sources), Recs(Recs), + StoreFilename(StoreFilename), Vf(Version.FileList()), Trusted(false) { Retries = _config->FindI("Acquire::Retries",0); @@ -2494,7 +2621,7 @@ pkgAcqArchive::pkgAcqArchive(pkgAcquire *Owner,pkgSourceList *Sources, // 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; } @@ -2560,15 +2687,17 @@ bool pkgAcqArchive::QueueNext() { for (; Vf.end() == false; ++Vf) { + pkgCache::PkgFileIterator const PkgF = Vf.File(); // Ignore not source sources - if ((Vf.File()->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(Vf.File(),Index) == false) + if (Sources->FindIndex(PkgF, Index) == false) continue; - + LocalSource = PkgF.Flagged(pkgCache::Flag::LocalSource); + // only try to get a trusted package from another source if that source // is also trusted if(Trusted && !Index->IsTrusted()) @@ -2668,37 +2797,14 @@ bool pkgAcqArchive::QueueNext() // AcqArchive::Done - Finished fetching /*{{{*/ // --------------------------------------------------------------------- /* */ -void pkgAcqArchive::Done(string Message,unsigned long long Size, HashStringList const &CalcHashes, - pkgAcquire::MethodConfig *Cfg) +void pkgAcqArchive::Done(string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cfg) { - Item::Done(Message, Size, CalcHashes, Cfg); - - // Check the size - if (Size != Version->Size) - { - RenameOnError(SizeMismatch); - return; - } - - // FIXME: could this empty() check impose *any* sort of security issue? - if(ExpectedHashes.usable() && ExpectedHashes != CalcHashes) - { - RenameOnError(HashSumMismatch); - printHashSumComparision(DestFile, ExpectedHashes, CalcHashes); - return; - } + 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; @@ -2713,23 +2819,17 @@ void pkgAcqArchive::Done(string Message,unsigned long long Size, HashStringList Complete = true; } /*}}}*/ -// Acquire::Item::GetFinalFilename - Return the full final file path /*{{{*/ -std::string pkgAcqArchive::GetFinalFilename() const -{ - return _config->FindDir("Dir::Cache::Archives") + flNotDir(StoreFilename); -} - /*}}}*/ // AcqArchive::Failed - Failure handler /*{{{*/ // --------------------------------------------------------------------- /* Here we try other sources */ -void pkgAcqArchive::Failed(string Message,pkgAcquire::MethodConfig *Cnf) +void pkgAcqArchive::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf) { Item::Failed(Message,Cnf); - /* We don't really want to retry on failed media swaps, this prevents + /* We don't really want to retry on failed media swaps, this prevents that. An interesting observation is that permanent failures are not recorded. */ - if (Cnf->Removable == true && + if (Cnf->Removable == true && StringToBool(LookupTag(Message,"Transient-Failure"),false) == true) { // Vf = Version.FileList(); @@ -2757,21 +2857,12 @@ void pkgAcqArchive::Failed(string Message,pkgAcquire::MethodConfig *Cnf) } } /*}}}*/ -// AcqArchive::IsTrusted - Determine whether this archive comes from a trusted source /*{{{*/ -// --------------------------------------------------------------------- -#if APT_PKG_ABI >= 413 -APT_PURE bool pkgAcqArchive::IsTrusted() const -#else -APT_PURE bool pkgAcqArchive::IsTrusted() -#endif +APT_PURE bool pkgAcqArchive::IsTrusted() const /*{{{*/ { return Trusted; } /*}}}*/ -// AcqArchive::Finished - Fetching has finished, tidy up /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void pkgAcqArchive::Finished() +void pkgAcqArchive::Finished() /*{{{*/ { if (Status == pkgAcquire::Item::StatDone && Complete == true) @@ -2779,17 +2870,225 @@ void pkgAcqArchive::Finished() StoreFilename = string(); } /*}}}*/ +std::string pkgAcqArchive::DescURI() const /*{{{*/ +{ + return Desc.URI; +} + /*}}}*/ +std::string pkgAcqArchive::ShortDesc() const /*{{{*/ +{ + 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 /*{{{*/ -// --------------------------------------------------------------------- -/* The file is added to the queue */ -pkgAcqFile::pkgAcqFile(pkgAcquire *Owner,string URI, HashStringList const &Hashes, - unsigned long long Size,string Dsc,string ShortDesc, +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 IsIndexFile) : - Item(Owner, Hashes), IsIndexFile(IsIndexFile) + bool const IsIndexFile) : + Item(Owner), d(NULL), IsIndexFile(IsIndexFile), ExpectedHashes(Hashes) { Retries = _config->FindI("Acquire::Retries",0); - + if(!DestFilename.empty()) DestFile = DestFilename; else if(!DestDir.empty()) @@ -2804,7 +3103,7 @@ pkgAcqFile::pkgAcqFile(pkgAcquire *Owner,string URI, HashStringList const &Hashe // Set the short description to the archive component Desc.ShortDesc = ShortDesc; - + // Get the transfer sizes FileSize = Size; struct stat Buf; @@ -2821,37 +3120,20 @@ pkgAcqFile::pkgAcqFile(pkgAcquire *Owner,string URI, HashStringList const &Hashe } /*}}}*/ // AcqFile::Done - Item downloaded OK /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void pkgAcqFile::Done(string Message,unsigned long long Size,HashStringList const &CalcHashes, - pkgAcquire::MethodConfig *Cnf) +void pkgAcqFile::Done(string const &Message,HashStringList const &CalcHashes, + pkgAcquire::MethodConfig const * const Cnf) { - Item::Done(Message,Size,CalcHashes,Cnf); - - // Check the hash - if(ExpectedHashes.usable() && ExpectedHashes != CalcHashes) - { - RenameOnError(HashSumMismatch); - printHashSumComparision(DestFile, ExpectedHashes, CalcHashes); - return; - } - - string FileName = LookupTag(Message,"Filename"); - if (FileName.empty() == true) - { - Status = StatError; - ErrorText = "Method gave a blank filename"; - return; - } + Item::Done(Message,CalcHashes,Cnf); + std::string const FileName = LookupTag(Message,"Filename"); Complete = true; - + // The files timestamp matches if (StringToBool(LookupTag(Message,"IMS-Hit"),false) == true) 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 || @@ -2861,7 +3143,7 @@ void pkgAcqFile::Done(string Message,unsigned long long Size,HashStringList cons QueueURI(Desc); return; } - + // Erase the file if it is a symlink so we can overwrite it struct stat St; if (lstat(DestFile.c_str(),&St) == 0) @@ -2869,7 +3151,7 @@ void pkgAcqFile::Done(string Message,unsigned long long Size,HashStringList cons if (S_ISLNK(St.st_mode) != 0) unlink(DestFile.c_str()); } - + // Symlink the file if (symlink(FileName.c_str(),DestFile.c_str()) != 0) { @@ -2881,14 +3163,14 @@ void pkgAcqFile::Done(string Message,unsigned long long Size,HashStringList cons ErrorText = msg.str(); Status = StatError; Complete = false; - } + } } } /*}}}*/ // AcqFile::Failed - Failure handler /*{{{*/ // --------------------------------------------------------------------- /* Here we try other sources */ -void pkgAcqFile::Failed(string Message,pkgAcquire::MethodConfig *Cnf) +void pkgAcqFile::Failed(string const &Message, pkgAcquire::MethodConfig const * const Cnf) { Item::Failed(Message,Cnf); @@ -2905,17 +3187,11 @@ void pkgAcqFile::Failed(string Message,pkgAcquire::MethodConfig *Cnf) } /*}}}*/ -// AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/ -// --------------------------------------------------------------------- -/* The only header we use is the last-modified header. */ -#if APT_PKG_ABI >= 413 -string pkgAcqFile::Custom600Headers() const -#else -string pkgAcqFile::Custom600Headers() -#endif +string pkgAcqFile::Custom600Headers() const /*{{{*/ { if (IsIndexFile) return "\nIndex-File: true"; return ""; } /*}}}*/ +pkgAcqFile::~pkgAcqFile() {} diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index 07c86f31b..d6bcdafcb 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -1,26 +1,26 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: acquire-item.h,v 1.26.2.3 2004/01/02 18:51:00 mdz Exp $ /* ###################################################################### Acquire Item - Item to acquire When an item is instantiated it will add it self to the local list in - the Owner Acquire class. Derived classes will then call QueueURI to - register all the URI's they wish to fetch at the initial moment. - + the Owner Acquire class. Derived classes will then call QueueURI to + register all the URI's they wish to fetch at the initial moment. + Three item classes are provided to provide functionality for downloading of Index, Translation and Packages files. - + A Archive class is provided for downloading .deb files. It does Hash checking and source location as well as a retry algorithm. - + ##################################################################### */ /*}}}*/ #ifndef PKGLIB_ACQUIRE_ITEM_H #define PKGLIB_ACQUIRE_ITEM_H #include <apt-pkg/acquire.h> +#include <apt-pkg/indexfile.h> #include <apt-pkg/hashes.h> #include <apt-pkg/weakptr.h> #include <apt-pkg/pkgcache.h> @@ -28,13 +28,11 @@ #include <string> #include <vector> +#include <map> #ifndef APT_8_CLEANER_HEADERS -#include <apt-pkg/indexfile.h> -#include <apt-pkg/vendor.h> #include <apt-pkg/sourcelist.h> #include <apt-pkg/pkgrecords.h> -#include <apt-pkg/indexrecords.h> #endif /** \addtogroup acquire @@ -43,13 +41,14 @@ * \file acquire-item.h */ -class indexRecords; class pkgRecords; class pkgSourceList; -class IndexTarget; -class pkgAcqMetaBase; +class pkgAcqMetaClearSig; +class pkgAcqIndexMergeDiffs; +class metaIndex; -/** \brief Represents the process by which a pkgAcquire object should {{{ +class pkgAcquire::Item : public WeakPointable /*{{{*/ +/** \brief Represents the process by which a pkgAcquire object should * retrieve a file or a collection of files. * * By convention, Item subclasses should insert themselves into the @@ -61,46 +60,7 @@ class pkgAcqMetaBase; * * \see pkgAcquire */ -class pkgAcquire::Item : public WeakPointable -{ - friend class pkgAcqMetaBase; - - void *d; - - protected: - - /** \brief The acquire object with which this item is associated. */ - pkgAcquire *Owner; - - /** \brief Insert this item into its owner's queue. - * - * The method is designed to check if the request would end - * in an IMSHit and if it determines that it would, it isn't - * queueing the Item and instead sets it to completion instantly. - * - * \param Item Metadata about this item (its URI and - * description). - * \return true if the item was inserted, false if IMSHit was detected - */ - virtual bool QueueURI(ItemDesc &Item); - - /** \brief Remove this item from its owner's queue. */ - void Dequeue(); - - /** \brief Rename a file without modifying its timestamp. - * - * Many item methods call this as their final action. - * - * \param From The file to be renamed. - * - * \param To The new name of \a From. If \a To exists it will be - * overwritten. - */ - bool Rename(std::string From,std::string To); - - /** \brief Get the full pathname of the final file for the current URI */ - virtual std::string GetFinalFilename() const; - +{ public: /** \brief The current status of this item. */ @@ -125,7 +85,7 @@ class pkgAcquire::Item : public WeakPointable */ StatAuthError, - /** \brief The item was could not be downloaded because of + /** \brief The item was could not be downloaded because of * a transient network error (e.g. network down) */ StatTransientNetworkError, @@ -153,11 +113,11 @@ class pkgAcquire::Item : public WeakPointable std::string ActiveSubprocess; /** \brief A client-supplied unique identifier. - * + * * This field is initalized to 0; it is meant to be filled in by * clients that wish to use it to uniquely identify items. * - * \todo it's unused in apt itself + * APT progress reporting will store an ID there as shown in "Get:42 …" */ unsigned long ID; @@ -173,6 +133,7 @@ class pkgAcquire::Item : public WeakPointable * download progress indicator's overall statistics. */ bool Local; + std::string UsedMirror; /** \brief The number of fetch queues into which this item has been @@ -185,9 +146,6 @@ class pkgAcquire::Item : public WeakPointable */ unsigned int QueueCounter; - /** \brief TransactionManager */ - pkgAcqMetaBase *TransactionManager; - /** \brief The number of additional fetch items that are expected * once this item is done. * @@ -197,15 +155,12 @@ class pkgAcquire::Item : public WeakPointable * progress. */ unsigned int ExpectedAdditionalItems; - + /** \brief The name of the file into which the retrieved object * will be written. */ std::string DestFile; - /** \brief storge name until a transaction is finished */ - std::string PartialFile; - /** \brief Invoked by the acquire worker when the object couldn't * be fetched. * @@ -219,7 +174,29 @@ class pkgAcquire::Item : public WeakPointable * * \sa pkgAcqMethod */ - virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); + + /** \brief Invoked by the acquire worker to check if the successfully + * fetched object is also the objected we wanted to have. + * + * Note that the object might \e not have been written to + * DestFile; check for the presence of an Alt-Filename entry in + * Message to find the file to which it was really written. + * + * This is called before Done is called and can prevent it by returning + * \b false which will result in Failed being called instead. + * + * You should prefer to use this method over calling Failed() from Done() + * as this has e.g. the wrong progress reporting. + * + * \param Message Data from the acquire method. Use LookupTag() + * to parse it. + * \param Cnf The method via which the object was fetched. + * + * \sa pkgAcqMethod + */ + virtual bool VerifyDone(std::string const &Message, + pkgAcquire::MethodConfig const * const Cnf); /** \brief Invoked by the acquire worker when the object was * fetched successfully. @@ -234,25 +211,24 @@ class pkgAcquire::Item : public WeakPointable * * \param Message Data from the acquire method. Use LookupTag() * to parse it. - * \param Size The size of the object that was fetched. * \param Hashes The HashSums of the object that was fetched. * \param Cnf The method via which the object was fetched. * * \sa pkgAcqMethod */ - virtual void Done(std::string Message, unsigned long long Size, HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cnf); + virtual void Done(std::string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cnf); /** \brief Invoked when the worker starts to fetch this object. * * \param Message RFC822-formatted data from the worker process. * Use LookupTag() to parse it. * - * \param Size The size of the object being fetched. + * \param Hashes The expected hashes of the object being fetched. * * \sa pkgAcqMethod */ - virtual void Start(std::string Message,unsigned long long Size); + virtual void Start(std::string const &Message, unsigned long long const Size); /** \brief Custom headers to be sent to the fetch process. * @@ -262,61 +238,56 @@ class pkgAcquire::Item : public WeakPointable * line, so they should (if nonempty) have a leading newline and * no trailing newline. */ -#if APT_PKG_ABI >= 413 - virtual std::string Custom600Headers() const {return std::string();}; -#else - virtual std::string Custom600Headers() {return std::string();}; -#endif + virtual std::string Custom600Headers() const; /** \brief A "descriptive" URI-like string. * * \return a URI that should be used to describe what is being fetched. */ - virtual std::string DescURI() = 0; + virtual std::string DescURI() const = 0; /** \brief Short item description. * * \return a brief description of the object being fetched. */ - virtual std::string ShortDesc() {return DescURI();} + virtual std::string ShortDesc() const; /** \brief Invoked by the worker when the download is completely done. */ - virtual void Finished() {}; - - /** \brief HashSums + virtual void Finished(); + + /** \return HashSums the DestFile is supposed to have in this stage */ + virtual HashStringList GetExpectedHashes() const = 0; + /** \return the 'best' hash for display proposes like --print-uris */ + std::string HashSum() const; + + /** \return if having no hashes is a hard failure or not * - * \return the HashSums of this object, if applicable; otherwise, an - * empty list. + * Idealy this is always \b true for every subclass, but thanks to + * historical grow we don't have hashes for all files in all cases + * in all steps, so it is slightly more complicated than it should be. */ - HashStringList HashSums() const {return ExpectedHashes;}; - std::string HashSum() const {HashStringList const hashes = HashSums(); HashString const * const hs = hashes.find(NULL); return hs != NULL ? hs->toStr() : ""; }; + virtual bool HashesRequired() const { return true; } /** \return the acquire process with which this item is associated. */ - pkgAcquire *GetOwner() const {return Owner;}; -#if APT_PKG_ABI < 413 - pkgAcquire *GetOwner() {return Owner;}; -#endif + pkgAcquire *GetOwner() const; + pkgAcquire::ItemDesc &GetItemDesc(); /** \return \b true if this object is being fetched from a trusted source. */ -#if APT_PKG_ABI >= 413 - virtual bool IsTrusted() const {return false;}; -#else - virtual bool IsTrusted() {return false;}; -#endif - + virtual bool IsTrusted() const; + /** \brief Report mirror problem - * + * * This allows reporting mirror failures back to a centralized * server. The apt-report-mirror-failure script is called for this - * + * * \param FailCode A short failure string that is send */ - void ReportMirrorFailure(std::string FailCode); + void ReportMirrorFailure(std::string const &FailCode); /** \brief Set the name of the current active subprocess * * See also #ActiveSubprocess */ - void SetActiveSubprocess(const std::string &subprocess); + void SetActiveSubprocess(std::string const &subprocess); /** \brief Initialize an item. * @@ -325,11 +296,8 @@ class pkgAcquire::Item : public WeakPointable * manually invoke QueueURI() to do so). * * \param Owner The new owner of this item. - * \param ExpectedHashes of the file represented by this item */ - Item(pkgAcquire *Owner, - HashStringList const &ExpectedHashes=HashStringList(), - pkgAcqMetaBase *TransactionManager=NULL); + explicit Item(pkgAcquire * const Owner); /** \brief Remove this item from its owner's queue by invoking * pkgAcquire::Remove. @@ -337,6 +305,11 @@ class pkgAcquire::Item : public WeakPointable virtual ~Item(); protected: + /** \brief The acquire object with which this item is associated. */ + pkgAcquire * const Owner; + + /** \brief The item that is currently being downloaded. */ + pkgAcquire::ItemDesc Desc; enum RenameOnErrorState { HashSumMismatch, @@ -354,63 +327,94 @@ class pkgAcquire::Item : public WeakPointable */ bool RenameOnError(RenameOnErrorState const state); + /** \brief Insert this item into its owner's queue. + * + * The method is designed to check if the request would end + * in an IMSHit and if it determines that it would, it isn't + * queueing the Item and instead sets it to completion instantly. + * + * \param Item Metadata about this item (its URI and + * description). + * \return true if the item was inserted, false if IMSHit was detected + */ + virtual bool QueueURI(ItemDesc &Item); + + /** \brief Remove this item from its owner's queue. */ + void Dequeue(); + + /** \brief Rename a file without modifying its timestamp. + * + * Many item methods call this as their final action. + * + * \param From The file to be renamed. + * + * \param To The new name of \a From. If \a To exists it will be + * overwritten. If \a From and \a To are equal nothing happens. + */ + bool Rename(std::string const &From, std::string const &To); + + /** \brief Get the full pathname of the final file for the current URI */ + virtual std::string GetFinalFilename() const; + + private: + void * const d; + + friend class pkgAcqMetaBase; + friend class pkgAcqMetaClearSig; +}; + /*}}}*/ +class APT_HIDDEN pkgAcqTransactionItem: public pkgAcquire::Item /*{{{*/ +/** \brief baseclass for the indexes files to manage them all together */ +{ + void * const d; + protected: + IndexTarget const Target; + HashStringList GetExpectedHashesFor(std::string const &MetaKey) const; + + bool QueueURI(pkgAcquire::ItemDesc &Item) APT_OVERRIDE; + + public: + /** \brief storge name until a transaction is finished */ + std::string PartialFile; + + /** \brief TransactionManager */ + pkgAcqMetaClearSig * const TransactionManager; + enum TransactionStates { TransactionCommit, TransactionAbort, }; virtual bool TransactionState(TransactionStates const state); - /** \brief The HashSums of the item is supposed to have than done */ - HashStringList ExpectedHashes; - - /** \brief The item that is currently being downloaded. */ - pkgAcquire::ItemDesc Desc; -}; - /*}}}*/ -/** \brief Information about an index patch (aka diff). */ /*{{{*/ -struct APT_HIDDEN DiffInfo { - /** The filename of the diff. */ - std::string file; + virtual std::string DescURI() const APT_OVERRIDE { return Target.URI; } + virtual HashStringList GetExpectedHashes() const APT_OVERRIDE; + virtual std::string GetMetaKey() const; + virtual bool HashesRequired() const APT_OVERRIDE; - /** The hashes of the diff */ - HashStringList result_hashes; - /** The hashes of the file after the diff is applied */ - HashStringList patch_hashes; - - /** The size of the file after the diff is applied */ - unsigned long long result_size; + pkgAcqTransactionItem(pkgAcquire * const Owner, pkgAcqMetaClearSig * const TransactionManager, IndexTarget const &Target); + virtual ~pkgAcqTransactionItem(); - /** The size of the diff itself */ - unsigned long long patch_size; + friend class pkgAcqMetaBase; + friend class pkgAcqMetaClearSig; }; /*}}}*/ -class pkgAcqMetaBase : public pkgAcquire::Item /*{{{*/ +class APT_HIDDEN pkgAcqMetaBase : public pkgAcqTransactionItem /*{{{*/ +/** \brief the manager of a transaction */ { - void *d; - + void * const d; protected: - std::vector<Item*> Transaction; - - /** \brief A package-system-specific parser for the meta-index file. */ - indexRecords *MetaIndexParser; - indexRecords *LastMetaIndexParser; + std::vector<pkgAcqTransactionItem*> Transaction; /** \brief The index files which should be looked up in the meta-index * and then downloaded. */ - const std::vector<IndexTarget*>* IndexTargets; + std::vector<IndexTarget> const IndexTargets; /** \brief If \b true, the index's signature is currently being verified. */ bool AuthPass; - /** \brief The URI of the signature file. Unlike Desc.URI, this is - * never modified; it is used to determine the file that is being - * downloaded. - */ - std::string RealURI; - /** \brief Starts downloading the individual index files. * * \param verify If \b true, only indices whose expected hashsum @@ -419,7 +423,7 @@ class pkgAcqMetaBase : public pkgAcquire::Item /*{{{*/ * #StatAuthError if there is a mismatch). If verify is \b false, * no hashsum checking will be performed. */ - void QueueIndexes(bool verify); + void QueueIndexes(bool const verify); /** \brief Called when a file is finished being retrieved. * @@ -430,16 +434,12 @@ class pkgAcqMetaBase : public pkgAcquire::Item /*{{{*/ * \param Message The message block received from the fetch * subprocess. */ - bool CheckDownloadDone(pkgAcquire::Item * const I, const std::string &Message, HashStringList const &Hashes) const; + bool CheckDownloadDone(pkgAcqTransactionItem * const I, const std::string &Message, HashStringList const &Hashes) const; /** \brief Queue the downloaded Signature for verification */ - void QueueForSignatureVerify(pkgAcquire::Item * const I, std::string const &File, std::string const &Signature); + void QueueForSignatureVerify(pkgAcqTransactionItem * const I, std::string const &File, std::string const &Signature); -#if APT_PKG_ABI >= 413 - virtual std::string Custom600Headers() const; -#else - virtual std::string Custom600Headers(); -#endif + virtual std::string Custom600Headers() const APT_OVERRIDE; /** \brief Called when authentication succeeded. * @@ -450,7 +450,7 @@ class pkgAcqMetaBase : public pkgAcquire::Item /*{{{*/ * \param Message The message block received from the fetch * subprocess. */ - bool CheckAuthDone(std::string Message); + bool CheckAuthDone(std::string const &Message); /** Check if the current item should fail at this point */ bool CheckStopAuthentication(pkgAcquire::Item * const I, const std::string &Message); @@ -460,41 +460,40 @@ class pkgAcqMetaBase : public pkgAcquire::Item /*{{{*/ * * \return \b true if no fatal errors were encountered. */ - bool VerifyVendor(std::string Message); + bool VerifyVendor(std::string const &Message); - virtual bool TransactionState(TransactionStates const state); + virtual bool TransactionState(TransactionStates const state) APT_OVERRIDE; public: // This refers more to the Transaction-Manager than the actual file bool IMSHit; - virtual std::string DescURI() {return RealURI; }; - virtual bool QueueURI(pkgAcquire::ItemDesc &Item); + virtual bool QueueURI(pkgAcquire::ItemDesc &Item) APT_OVERRIDE; + virtual HashStringList GetExpectedHashes() const APT_OVERRIDE; + virtual bool HashesRequired() const APT_OVERRIDE; // transaction code - void Add(Item *I); + void Add(pkgAcqTransactionItem * const I); void AbortTransaction(); - bool TransactionHasError() APT_PURE; + bool TransactionHasError() const; void CommitTransaction(); /** \brief Stage (queue) a copy action when the transaction is committed */ - void TransactionStageCopy(Item *I, - const std::string &From, + void TransactionStageCopy(pkgAcqTransactionItem * const I, + const std::string &From, const std::string &To); /** \brief Stage (queue) a removal action when the transaction is committed */ - void TransactionStageRemoval(Item *I, const std::string &FinalFile); + void TransactionStageRemoval(pkgAcqTransactionItem * const I, const std::string &FinalFile); /** \brief Get the full pathname of the final file for the current URI */ - virtual std::string GetFinalFilename() const; + virtual std::string GetFinalFilename() const APT_OVERRIDE; - pkgAcqMetaBase(pkgAcquire *Owner, - const std::vector<IndexTarget*>* IndexTargets, - indexRecords* MetaIndexParser, - std::string const &RealURI, - HashStringList const &ExpectedHashes=HashStringList(), - pkgAcqMetaBase *TransactionManager=NULL); + pkgAcqMetaBase(pkgAcquire * const Owner, pkgAcqMetaClearSig * const TransactionManager, + std::vector<IndexTarget> const &IndexTargets, + IndexTarget const &DataTarget); + virtual ~pkgAcqMetaBase(); }; /*}}}*/ /** \brief An item that is responsible for downloading the meta-index {{{ @@ -509,39 +508,27 @@ class pkgAcqMetaBase : public pkgAcquire::Item /*{{{*/ */ class APT_HIDDEN pkgAcqMetaIndex : public pkgAcqMetaBase { - void *d; - + void * const d; protected: - std::string URIDesc; - std::string ShortDesc; - - /** \brief The URI of the meta-index file for the detached signature */ - std::string MetaIndexSigURI; - - /** \brief A "URI-style" description of the meta-index file */ - std::string MetaIndexSigURIDesc; - - /** \brief A brief description of the meta-index file */ - std::string MetaIndexSigShortDesc; + IndexTarget const DetachedSigTarget; /** \brief delayed constructor */ - void Init(std::string URIDesc, std::string ShortDesc); - + void Init(std::string const &URIDesc, std::string const &ShortDesc); + public: + virtual std::string DescURI() const APT_OVERRIDE; // Specialized action members - virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); - virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cnf); - virtual void Finished(); + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; + virtual void Done(std::string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; + virtual void Finished() APT_OVERRIDE; /** \brief Create a new pkgAcqMetaIndex. */ - pkgAcqMetaIndex(pkgAcquire *Owner, - pkgAcqMetaBase *TransactionManager, - std::string URI,std::string URIDesc, std::string ShortDesc, - std::string MetaIndexSigURI, std::string MetaIndexSigURIDesc, std::string MetaIndexSigShortDesc, - const std::vector<IndexTarget*>* IndexTargets, - indexRecords* MetaIndexParser); + pkgAcqMetaIndex(pkgAcquire * const Owner, pkgAcqMetaClearSig * const TransactionManager, + IndexTarget const &DataTarget, IndexTarget const &DetachedSigTarget, + std::vector<IndexTarget> const &IndexTargets); + virtual ~pkgAcqMetaIndex(); friend class pkgAcqMetaSig; }; @@ -554,9 +541,9 @@ class APT_HIDDEN pkgAcqMetaIndex : public pkgAcqMetaBase * * \sa pkgAcqMetaIndex */ -class APT_HIDDEN pkgAcqMetaSig : public pkgAcquire::Item +class APT_HIDDEN pkgAcqMetaSig : public pkgAcqTransactionItem { - void *d; + void * const d; pkgAcqMetaIndex * const MetaIndex; @@ -565,109 +552,65 @@ class APT_HIDDEN pkgAcqMetaSig : public pkgAcquire::Item protected: - /** \brief Long URI description used in the acquire system */ - std::string URIDesc; - - /** \brief URI used to get the file */ - std::string RealURI; - /** \brief Get the full pathname of the final file for the current URI */ - virtual std::string GetFinalFilename() const; + virtual std::string GetFinalFilename() const APT_OVERRIDE; public: - virtual std::string DescURI() {return RealURI;}; + virtual bool HashesRequired() const APT_OVERRIDE { return false; } // Specialized action members - virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); - virtual void Done(std::string Message,unsigned long long Size, - HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cnf); + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; + virtual void Done(std::string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; + virtual std::string Custom600Headers() const APT_OVERRIDE; /** \brief Create a new pkgAcqMetaSig. */ - pkgAcqMetaSig(pkgAcquire *Owner, - pkgAcqMetaBase *TransactionManager, - std::string const &URI,std::string const &URIDesc, - std::string const &ShortDesc, pkgAcqMetaIndex * const MetaIndex); + pkgAcqMetaSig(pkgAcquire * const Owner, pkgAcqMetaClearSig * const TransactionManager, + IndexTarget const &Target, pkgAcqMetaIndex * const MetaIndex); virtual ~pkgAcqMetaSig(); }; /*}}}*/ /** \brief An item repsonsible for downloading clearsigned metaindexes {{{*/ class APT_HIDDEN pkgAcqMetaClearSig : public pkgAcqMetaIndex { - void *d; - - /** \brief The URI of the meta-index file for the detached signature */ - std::string MetaIndexURI; - - /** \brief A "URI-style" description of the meta-index file */ - std::string MetaIndexURIDesc; - - /** \brief A brief description of the meta-index file */ - std::string MetaIndexShortDesc; + void * const d; - /** \brief The URI of the detached meta-signature file if the clearsigned one failed. */ - std::string MetaSigURI; + IndexTarget const ClearsignedTarget; + IndexTarget const DetachedDataTarget; - /** \brief A "URI-style" description of the meta-signature file */ - std::string MetaSigURIDesc; - - /** \brief A brief description of the meta-signature file */ - std::string MetaSigShortDesc; + public: + /** \brief A package-system-specific parser for the meta-index file. */ + metaIndex *MetaIndexParser; + metaIndex *LastMetaIndexParser; -public: - virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); -#if APT_PKG_ABI >= 413 - virtual std::string Custom600Headers() const; -#else - virtual std::string Custom600Headers(); -#endif - virtual void Done(std::string Message,unsigned long long Size, - HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cnf); + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; + virtual std::string Custom600Headers() const APT_OVERRIDE; + virtual bool VerifyDone(std::string const &Message, pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; + virtual void Done(std::string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; /** \brief Create a new pkgAcqMetaClearSig. */ - pkgAcqMetaClearSig(pkgAcquire *Owner, - std::string const &URI, std::string const &URIDesc, std::string const &ShortDesc, - std::string const &MetaIndexURI, std::string const &MetaIndexURIDesc, std::string const &MetaIndexShortDesc, - std::string const &MetaSigURI, std::string const &MetaSigURIDesc, std::string const &MetaSigShortDesc, - const std::vector<IndexTarget*>* IndexTargets, - indexRecords* MetaIndexParser); + pkgAcqMetaClearSig(pkgAcquire * const Owner, + IndexTarget const &ClearsignedTarget, + IndexTarget const &DetachedDataTarget, + IndexTarget const &DetachedSigTarget, + std::vector<IndexTarget> const &IndexTargets, + metaIndex * const MetaIndexParser); virtual ~pkgAcqMetaClearSig(); }; /*}}}*/ -/** \brief Common base class for all classes that deal with fetching {{{ - indexes - */ -class pkgAcqBaseIndex : public pkgAcquire::Item +/** \brief Common base class for all classes that deal with fetching indexes {{{*/ +class APT_HIDDEN pkgAcqBaseIndex : public pkgAcqTransactionItem { - void *d; - - protected: - /** \brief Pointer to the IndexTarget data - */ - const struct IndexTarget * Target; - - /** \brief Pointer to the indexRecords parser */ - indexRecords *MetaIndexParser; - - /** \brief The MetaIndex Key */ - std::string MetaKey; - - /** \brief The URI of the index file to recreate at our end (either - * by downloading it or by applying partial patches). - */ - std::string RealURI; - - bool VerifyHashByMetaKey(HashStringList const &Hashes); + void * const d; + public: /** \brief Get the full pathname of the final file for the current URI */ - virtual std::string GetFinalFilename() const; + virtual std::string GetFinalFilename() const APT_OVERRIDE; - pkgAcqBaseIndex(pkgAcquire *Owner, - pkgAcqMetaBase *TransactionManager, - struct IndexTarget const * const Target, - HashStringList const &ExpectedHashes, - indexRecords *MetaIndexParser); + pkgAcqBaseIndex(pkgAcquire * const Owner, pkgAcqMetaClearSig * const TransactionManager, + IndexTarget const &Target); + virtual ~pkgAcqBaseIndex(); }; /*}}}*/ /** \brief An item that is responsible for fetching an index file of {{{ @@ -681,39 +624,32 @@ class pkgAcqBaseIndex : public pkgAcquire::Item */ class APT_HIDDEN pkgAcqDiffIndex : public pkgAcqBaseIndex { - void *d; + void * const d; + std::vector<pkgAcqIndexMergeDiffs*> * diffs; protected: /** \brief If \b true, debugging information will be written to std::clog. */ bool Debug; - /** \brief The index file which will be patched to generate the new - * file. - */ - std::string CurrentPackagesFile; - /** \brief A description of the Packages file (stored in * pkgAcquire::ItemDesc::Description). */ std::string Description; /** \brief Get the full pathname of the final file for the current URI */ - virtual std::string GetFinalFilename() const; + virtual std::string GetFinalFilename() const APT_OVERRIDE; - virtual bool QueueURI(pkgAcquire::ItemDesc &Item); + virtual bool QueueURI(pkgAcquire::ItemDesc &Item) APT_OVERRIDE; - virtual bool TransactionState(TransactionStates const state); + virtual bool TransactionState(TransactionStates const state) APT_OVERRIDE; public: // Specialized action members - virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); - virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cnf); - virtual std::string DescURI() {return RealURI + "Index";}; -#if APT_PKG_ABI >= 413 - virtual std::string Custom600Headers() const; -#else - virtual std::string Custom600Headers(); -#endif + virtual void Failed(std::string const &Message, pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; + virtual void Done(std::string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; + virtual std::string DescURI() const APT_OVERRIDE {return Target.URI + "Index";}; + virtual std::string Custom600Headers() const APT_OVERRIDE; + virtual std::string GetMetaKey() const APT_OVERRIDE; /** \brief Parse the Index file for a set of Packages diffs. * @@ -725,7 +661,7 @@ class APT_HIDDEN pkgAcqDiffIndex : public pkgAcqBaseIndex * \return \b true if the Index file was successfully parsed, \b * false otherwise. */ - bool ParseDiffIndex(std::string IndexDiffFile); + bool ParseDiffIndex(std::string const &IndexDiffFile); /** \brief Create a new pkgAcqDiffIndex. * @@ -736,18 +672,28 @@ class APT_HIDDEN pkgAcqDiffIndex : public pkgAcqBaseIndex * \param URIDesc A long description of the list file to download. * * \param ShortDesc A short description of the list file to download. - * - * \param ExpectedHashes The list file's hashsums which are expected. */ - pkgAcqDiffIndex(pkgAcquire *Owner, - pkgAcqMetaBase *TransactionManager, - struct IndexTarget const * const Target, - HashStringList const &ExpectedHashes, - indexRecords *MetaIndexParser); + pkgAcqDiffIndex(pkgAcquire * const Owner, pkgAcqMetaClearSig * const TransactionManager, + IndexTarget const &Target); + virtual ~pkgAcqDiffIndex(); private: APT_HIDDEN void QueueOnIMSHit() const; }; /*}}}*/ +struct APT_HIDDEN DiffInfo { /*{{{*/ + /** The filename of the diff. */ + std::string file; + + /** The hashes of the file after the diff is applied */ + HashStringList result_hashes; + + /** The hashes of the diff */ + HashStringList patch_hashes; + + /** The hashes of the compressed diff */ + HashStringList download_hashes; +}; + /*}}}*/ /** \brief An item that is responsible for fetching client-merge patches {{{ * that need to be applied to a given package index file. * @@ -761,7 +707,7 @@ class APT_HIDDEN pkgAcqDiffIndex : public pkgAcqBaseIndex */ class APT_HIDDEN pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex { - void *d; + void * const d; protected: @@ -801,10 +747,13 @@ class APT_HIDDEN pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex * This method will fall back to downloading the whole index file * outright; its arguments are ignored. */ - virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); - virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cnf); - virtual std::string DescURI() {return RealURI + "Index";}; + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; + virtual void Done(std::string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; + virtual std::string Custom600Headers() const APT_OVERRIDE; + virtual std::string DescURI() const APT_OVERRIDE {return Target.URI + "Index";}; + virtual HashStringList GetExpectedHashes() const APT_OVERRIDE; + virtual bool HashesRequired() const APT_OVERRIDE; /** \brief Create an index merge-diff item. * @@ -817,23 +766,16 @@ class APT_HIDDEN pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex * * \param ShortDesc A brief description of this item. * - * \param ExpectedHashes The expected md5sum of the completely - * reconstructed package index file; the index file will be tested - * against this value when it is entirely reconstructed. - * * \param patch contains infos about the patch this item is supposed * to download which were read from the index * * \param allPatches contains all related items so that each item can * check if it was the last one to complete the download step */ - pkgAcqIndexMergeDiffs(pkgAcquire *Owner, - pkgAcqMetaBase *TransactionManager, - struct IndexTarget const * const Target, - HashStringList const &ExpectedHash, - indexRecords *MetaIndexParser, - DiffInfo const &patch, + pkgAcqIndexMergeDiffs(pkgAcquire * const Owner, pkgAcqMetaClearSig * const TransactionManager, + IndexTarget const &Target, DiffInfo const &patch, std::vector<pkgAcqIndexMergeDiffs*> const * const allPatches); + virtual ~pkgAcqIndexMergeDiffs(); }; /*}}}*/ /** \brief An item that is responsible for fetching server-merge patches {{{ @@ -849,7 +791,7 @@ class APT_HIDDEN pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex */ class APT_HIDDEN pkgAcqIndexDiffs : public pkgAcqBaseIndex { - void *d; + void * const d; private: @@ -875,7 +817,7 @@ class APT_HIDDEN pkgAcqIndexDiffs : public pkgAcqBaseIndex * \param allDone If \b true, the file was entirely reconstructed, * and its md5sum is verified. */ - APT_HIDDEN void Finish(bool allDone=false); + APT_HIDDEN void Finish(bool const allDone=false); protected: @@ -905,26 +847,26 @@ class APT_HIDDEN pkgAcqIndexDiffs : public pkgAcqBaseIndex /** \brief The diff is currently being fetched. */ StateFetchDiff, - - /** \brief The diff is currently being uncompressed. */ - StateUnzipDiff, // FIXME: No longer used /** \brief The diff is currently being applied. */ StateApplyDiff } State; public: - + /** \brief Called when the patch file failed to be downloaded. * * This method will fall back to downloading the whole index file * outright; its arguments are ignored. */ - virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; - virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cnf); - virtual std::string DescURI() {return RealURI + "IndexDiffs";}; + virtual void Done(std::string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; + virtual std::string Custom600Headers() const APT_OVERRIDE; + virtual std::string DescURI() const APT_OVERRIDE {return Target.URI + "IndexDiffs";}; + virtual HashStringList GetExpectedHashes() const APT_OVERRIDE; + virtual bool HashesRequired() const APT_OVERRIDE; /** \brief Create an index diff item. * @@ -940,20 +882,14 @@ class APT_HIDDEN pkgAcqIndexDiffs : public pkgAcqBaseIndex * * \param ShortDesc A brief description of this item. * - * \param ExpectedHashes The expected hashsums of the completely - * reconstructed package index file; the index file will be tested - * against this value when it is entirely reconstructed. - * * \param diffs The remaining diffs from the index of diffs. They * should be ordered so that each diff appears before any diff * that depends on it. */ - pkgAcqIndexDiffs(pkgAcquire *Owner, - pkgAcqMetaBase *TransactionManager, - struct IndexTarget const * const Target, - HashStringList const &ExpectedHash, - indexRecords *MetaIndexParser, - std::vector<DiffInfo> diffs=std::vector<DiffInfo>()); + pkgAcqIndexDiffs(pkgAcquire * const Owner, pkgAcqMetaClearSig * const TransactionManager, + IndexTarget const &Target, + std::vector<DiffInfo> const &diffs=std::vector<DiffInfo>()); + virtual ~pkgAcqIndexDiffs(); }; /*}}}*/ /** \brief An acquire item that is responsible for fetching an index {{{ @@ -965,7 +901,7 @@ class APT_HIDDEN pkgAcqIndexDiffs : public pkgAcqBaseIndex */ class APT_HIDDEN pkgAcqIndex : public pkgAcqBaseIndex { - void *d; + void * const d; protected: @@ -981,16 +917,16 @@ class APT_HIDDEN pkgAcqIndex : public pkgAcqBaseIndex AllStages Stage; /** \brief Handle what needs to be done when the download is done */ - void StageDownloadDone(std::string Message, + void StageDownloadDone(std::string const &Message, HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cfg); + pkgAcquire::MethodConfig const * const Cfg); /** \brief Handle what needs to be done when the decompression/copy is * done */ - void StageDecompressDone(std::string Message, + void StageDecompressDone(std::string const &Message, HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cfg); + pkgAcquire::MethodConfig const * const Cfg); /** \brief If \b set, this partially downloaded file will be * removed when the download completes. @@ -1006,7 +942,7 @@ class APT_HIDDEN pkgAcqIndex : public pkgAcqBaseIndex std::string CurrentCompressionExtension; /** \brief Do the changes needed to fetch via AptByHash (if needed) */ - void InitByHashIfNeeded(const std::string MetaKey); + void InitByHashIfNeeded(); /** \brief Auto select the right compression to use */ void AutoSelectCompression(); @@ -1014,90 +950,27 @@ class APT_HIDDEN pkgAcqIndex : public pkgAcqBaseIndex /** \brief Schedule file for verification after a IMS hit */ void ReverifyAfterIMS(); - /** \brief Validate the downloaded index file */ - bool ValidateFile(const std::string &FileName); - /** \brief Get the full pathname of the final file for the current URI */ - virtual std::string GetFinalFilename() const; + virtual std::string GetFinalFilename() const APT_OVERRIDE; - virtual bool TransactionState(TransactionStates const state); + virtual bool TransactionState(TransactionStates const state) APT_OVERRIDE; public: // Specialized action members - virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); - virtual void Done(std::string Message,unsigned long long Size, - HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cnf); -#if APT_PKG_ABI >= 413 - virtual std::string Custom600Headers() const; -#else - virtual std::string Custom600Headers(); -#endif - virtual std::string DescURI() {return Desc.URI;}; - - /** \brief Create a pkgAcqIndex. - * - * \param Owner The pkgAcquire object with which this item is - * associated. - * - * \param URI The URI of the index file that is to be downloaded. - * - * \param URIDesc A "URI-style" description of this index file. - * - * \param ShortDesc A brief description of this index file. - * - * \param ExpectedHashes The expected hashsum of this index file. - * - * \param compressExt The compression-related extension with which - * this index file should be downloaded, or "" to autodetect - * Compression types can be set with config Acquire::CompressionTypes, - * default is ".lzma" or ".bz2" (if the needed binaries are present) - * fallback is ".gz" or none. - */ - pkgAcqIndex(pkgAcquire *Owner,std::string URI,std::string URIDesc, - std::string ShortDesc, HashStringList const &ExpectedHashes); - pkgAcqIndex(pkgAcquire *Owner, pkgAcqMetaBase *TransactionManager, - IndexTarget const * const Target, - HashStringList const &ExpectedHash, - indexRecords *MetaIndexParser); - - void Init(std::string const &URI, std::string const &URIDesc, - std::string const &ShortDesc); -}; - /*}}}*/ -/** \brief Information about an index file. */ /*{{{*/ -class APT_HIDDEN IndexTarget -{ - void *d; - - public: - /** \brief A URI from which the index file can be downloaded. */ - std::string URI; - - /** \brief A description of the index file. */ - std::string Description; + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; + virtual void Done(std::string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; + virtual std::string Custom600Headers() const APT_OVERRIDE; + virtual std::string DescURI() const APT_OVERRIDE {return Desc.URI;}; + virtual std::string GetMetaKey() const APT_OVERRIDE; - /** \brief A shorter description of the index file. */ - std::string ShortDesc; + pkgAcqIndex(pkgAcquire * const Owner, pkgAcqMetaClearSig * const TransactionManager, + IndexTarget const &Target); + virtual ~pkgAcqIndex(); - /** \brief The key by which this index file should be - * looked up within the meta signature file. - */ - std::string MetaKey; - - virtual bool IsOptional() const { - return false; - } -}; - /*}}}*/ -/** \brief Information about an optional index file. */ /*{{{*/ -class APT_HIDDEN OptionalIndexTarget : public IndexTarget -{ - void *d; - - virtual bool IsOptional() const { - return true; - } + private: + APT_HIDDEN void Init(std::string const &URI, std::string const &URIDesc, + std::string const &ShortDesc); }; /*}}}*/ /** \brief An item that is responsible for fetching a package file. {{{ @@ -1107,7 +980,10 @@ class APT_HIDDEN OptionalIndexTarget : public IndexTarget */ class pkgAcqArchive : public pkgAcquire::Item { - void *d; + void * const d; + + bool LocalSource; + HashStringList ExpectedHashes; protected: /** \brief The package version being fetched. */ @@ -1141,27 +1017,25 @@ class pkgAcqArchive : public pkgAcquire::Item /** \brief \b true if this version file is being downloaded from a * trusted source. */ - bool Trusted; + bool Trusted; /** \brief Queue up the next available file for this version. */ bool QueueNext(); /** \brief Get the full pathname of the final file for the current URI */ - virtual std::string GetFinalFilename() const; + virtual std::string GetFinalFilename() const APT_OVERRIDE; public: - virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); - virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cnf); - virtual std::string DescURI() {return Desc.URI;}; - virtual std::string ShortDesc() {return Desc.ShortDesc;}; - virtual void Finished(); -#if APT_PKG_ABI >= 413 - virtual bool IsTrusted() const; -#else - virtual bool IsTrusted(); -#endif + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; + virtual void Done(std::string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; + virtual std::string DescURI() const APT_OVERRIDE; + virtual std::string ShortDesc() const APT_OVERRIDE; + virtual void Finished() APT_OVERRIDE; + virtual bool IsTrusted() const APT_OVERRIDE; + virtual HashStringList GetExpectedHashes() const APT_OVERRIDE; + virtual bool HashesRequired() const APT_OVERRIDE; /** \brief Create a new pkgAcqArchive. * @@ -1181,9 +1055,124 @@ class pkgAcqArchive : public pkgAcquire::Item * basename in the constructor, and filled in with a fully * qualified filename once the download finishes. */ - pkgAcqArchive(pkgAcquire *Owner,pkgSourceList *Sources, - pkgRecords *Recs,pkgCache::VerIterator const &Version, + pkgAcqArchive(pkgAcquire * const Owner,pkgSourceList * const Sources, + pkgRecords * const Recs,pkgCache::VerIterator const &Version, std::string &StoreFilename); + virtual ~pkgAcqArchive(); +}; + /*}}}*/ +/** \brief Retrieve the changelog for the given version {{{ + * + * Downloads the changelog to a temporary file it will also remove again + * while it is deconstructed or downloads it to a named location. + */ +class pkgAcqChangelog : public pkgAcquire::Item +{ + void * const d; + std::string TemporaryDirectory; + std::string const SrcName; + std::string const SrcVersion; + + public: + // we will never have hashes for changelogs. + // If you need verified ones, download the deb and extract the changelog. + virtual HashStringList GetExpectedHashes() const APT_OVERRIDE { return HashStringList(); } + virtual bool HashesRequired() const APT_OVERRIDE { return false; } + + // Specialized action members + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; + virtual void Done(std::string const &Message, HashStringList const &CalcHashes, + pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; + virtual std::string DescURI() const APT_OVERRIDE {return Desc.URI;}; + + /** returns the URI to the changelog of this version + * + * @param Ver is the version to get the changelog for + * @return the URI which will be used to acquire the changelog + */ + static std::string URI(pkgCache::VerIterator const &Ver); + + /** returns the URI to the changelog of this version + * + * \param Rls is the Release file the package comes from + * \param Component in which the package resides, can be empty + * \param SrcName is the source package name + * \param SrcVersion is the source package version + * @return the URI which will be used to acquire the changelog + */ + static std::string URI(pkgCache::RlsFileIterator const &Rls, + char const * const Component, char const * const SrcName, + char const * const SrcVersion); + + /** returns the URI to the changelog of this version + * + * \param Template URI where CHANGEPATH has to be filled in + * \param Component in which the package resides, can be empty + * \param SrcName is the source package name + * \param SrcVersion is the source package version + * @return the URI which will be used to acquire the changelog + */ + static std::string URI(std::string const &Template, + char const * const Component, char const * const SrcName, + char const * const SrcVersion); + + /** returns the URI template for this release file + * + * \param Rls is a Release file + * @return the URI template to use for this release file + */ + static std::string URITemplate(pkgCache::RlsFileIterator const &Rls); + + /** \brief Create a new pkgAcqChangelog object. + * + * \param Owner The pkgAcquire object with which this object is + * associated. + * \param Ver is the version to get the changelog for + * \param DestDir The directory the file should be downloaded into. + * Will be an autocreated (and cleaned up) temporary directory if not set. + * \param DestFilename The filename the file should have in #DestDir + * Defaults to sourcepackagename.changelog if not set. + */ + pkgAcqChangelog(pkgAcquire * const Owner, pkgCache::VerIterator const &Ver, + std::string const &DestDir="", std::string const &DestFilename=""); + + /** \brief Create a new pkgAcqChangelog object. + * + * \param Owner The pkgAcquire object with which this object is + * associated. + * \param Rls is the Release file the package comes from + * \param Component in which the package resides, can be empty + * \param SrcName is the source package name + * \param SrcVersion is the source package version + * \param DestDir The directory the file should be downloaded into. + * Will be an autocreated (and cleaned up) temporary directory if not set. + * \param DestFilename The filename the file should have in #DestDir + * Defaults to sourcepackagename.changelog if not set. + */ + pkgAcqChangelog(pkgAcquire * const Owner, pkgCache::RlsFileIterator const &Rls, + char const * const Component, char const * const SrcName, char const * const SrcVersion, + std::string const &DestDir="", std::string const &DestFilename=""); + + /** \brief Create a new pkgAcqChangelog object. + * + * \param Owner The pkgAcquire object with which this object is + * associated. + * \param URI is to be used to get the changelog + * \param SrcName is the source package name + * \param SrcVersion is the source package version + * \param DestDir The directory the file should be downloaded into. + * Will be an autocreated (and cleaned up) temporary directory if not set. + * \param DestFilename The filename the file should have in #DestDir + * Defaults to sourcepackagename.changelog if not set. + */ + pkgAcqChangelog(pkgAcquire * const Owner, std::string const &URI, + char const * const SrcName, char const * const SrcVersion, + std::string const &DestDir="", std::string const &DestFilename=""); + + virtual ~pkgAcqChangelog(); + +private: + APT_HIDDEN void Init(std::string const &DestDir, std::string const &DestFilename); }; /*}}}*/ /** \brief Retrieve an arbitrary file to the current directory. {{{ @@ -1194,28 +1183,27 @@ class pkgAcqArchive : public pkgAcquire::Item */ class pkgAcqFile : public pkgAcquire::Item { - void *d; + void * const d; /** \brief How many times to retry the download, set from * Acquire::Retries. */ unsigned int Retries; - + /** \brief Should this file be considered a index file */ bool IsIndexFile; + HashStringList const ExpectedHashes; public: - + virtual HashStringList GetExpectedHashes() const APT_OVERRIDE; + virtual bool HashesRequired() const APT_OVERRIDE; + // Specialized action members - virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); - virtual void Done(std::string Message,unsigned long long Size, HashStringList const &CalcHashes, - pkgAcquire::MethodConfig *Cnf); - virtual std::string DescURI() {return Desc.URI;}; -#if APT_PKG_ABI >= 413 - virtual std::string Custom600Headers() const; -#else - virtual std::string Custom600Headers(); -#endif + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; + virtual void Done(std::string const &Message, HashStringList const &CalcHashes, + pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; + virtual std::string DescURI() const APT_OVERRIDE {return Desc.URI;}; + virtual std::string Custom600Headers() const APT_OVERRIDE; /** \brief Create a new pkgAcqFile object. * @@ -1248,10 +1236,11 @@ class pkgAcqFile : public pkgAcquire::Item * is the absolute name to which the file should be downloaded. */ - pkgAcqFile(pkgAcquire *Owner, std::string URI, HashStringList const &Hashes, unsigned long long Size, - std::string Desc, std::string ShortDesc, - const std::string &DestDir="", const std::string &DestFilename="", - bool IsIndexFile=false); + pkgAcqFile(pkgAcquire * const Owner, std::string const &URI, HashStringList const &Hashes, unsigned long long const Size, + std::string const &Desc, std::string const &ShortDesc, + std::string const &DestDir="", std::string const &DestFilename="", + bool const IsIndexFile=false); + virtual ~pkgAcqFile(); }; /*}}}*/ /** @} */ diff --git a/apt-pkg/acquire-method.cc b/apt-pkg/acquire-method.cc index c29ef469e..991e6780a 100644 --- a/apt-pkg/acquire-method.cc +++ b/apt-pkg/acquire-method.cc @@ -376,7 +376,10 @@ int pkgAcqMethod::Run(bool Single) Tmp->ExpectedHashes.push_back(HashString(*t, hash)); } char *End; - Tmp->MaximumSize = strtoll(LookupTag(Message, "Maximum-Size", "0").c_str(), &End, 10); + if (Tmp->ExpectedHashes.FileSize() > 0) + Tmp->MaximumSize = Tmp->ExpectedHashes.FileSize(); + else + Tmp->MaximumSize = strtoll(LookupTag(Message, "Maximum-Size", "0").c_str(), &End, 10); Tmp->Next = 0; // Append it to the list @@ -385,14 +388,14 @@ int pkgAcqMethod::Run(bool Single) *I = Tmp; if (QueueBack == 0) QueueBack = Tmp; - + // Notify that this item is to be fetched. - if (Fetch(Tmp) == false) + if (URIAcquire(Message, Tmp) == false) Fail(); - - break; - } - } + + break; + } + } } Exit(); @@ -400,8 +403,6 @@ int pkgAcqMethod::Run(bool Single) } /*}}}*/ // AcqMethod::PrintStatus - privately really send a log/status message /*{{{*/ -// --------------------------------------------------------------------- -/* */ void pkgAcqMethod::PrintStatus(char const * const header, const char* Format, va_list &args) const { @@ -456,7 +457,7 @@ void pkgAcqMethod::Redirect(const string &NewURI) // --------------------------------------------------------------------- /* */ pkgAcqMethod::FetchResult::FetchResult() : LastModified(0), - IMSHit(false), Size(0), ResumePoint(0) + IMSHit(false), Size(0), ResumePoint(0), d(NULL) { } /*}}}*/ @@ -477,5 +478,9 @@ void pkgAcqMethod::Dequeue() { /*{{{*/ delete Tmp; } /*}}}*/ - pkgAcqMethod::~pkgAcqMethod() {} + +pkgAcqMethod::FetchItem::FetchItem() : d(NULL) {} +pkgAcqMethod::FetchItem::~FetchItem() {} + +pkgAcqMethod::FetchResult::~FetchResult() {} diff --git a/apt-pkg/acquire-method.h b/apt-pkg/acquire-method.h index 399454892..cab2bda40 100644 --- a/apt-pkg/acquire-method.h +++ b/apt-pkg/acquire-method.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: acquire-method.h,v 1.15.2.1 2003/12/24 23:09:17 mdz Exp $ /* ###################################################################### Acquire Method - Method helper class + functions @@ -53,6 +52,11 @@ class pkgAcqMethod // for when we know it or a arbitrary limit when we don't know the // filesize (like a InRelease file) unsigned long long MaximumSize; + + FetchItem(); + virtual ~FetchItem(); + private: + void * const d; }; struct FetchResult @@ -67,6 +71,9 @@ class pkgAcqMethod void TakeHashes(class Hashes &Hash); FetchResult(); + virtual ~FetchResult(); + private: + void * const d; }; // State @@ -76,11 +83,12 @@ class pkgAcqMethod std::string FailReason; std::string UsedMirror; std::string IP; - + // Handlers for messages virtual bool Configuration(std::string Message); virtual bool Fetch(FetchItem * /*Item*/) {return true;}; - + virtual bool URIAcquire(std::string const &/*Message*/, FetchItem *Itm) { return Fetch(Itm); }; + // Outgoing messages void Fail(bool Transient = false); inline void Fail(const char *Why, bool Transient = false) {Fail(std::string(Why),Transient);}; diff --git a/apt-pkg/acquire-worker.cc b/apt-pkg/acquire-worker.cc index 9254e20a3..b15340448 100644 --- a/apt-pkg/acquire-worker.cc +++ b/apt-pkg/acquire-worker.cc @@ -26,7 +26,6 @@ #include <string> #include <vector> #include <iostream> -#include <sstream> #include <sys/stat.h> #include <stdlib.h> @@ -34,9 +33,7 @@ #include <signal.h> #include <stdio.h> #include <errno.h> -#include <sys/types.h> -#include <pwd.h> -#include <grp.h> +#include <sstream> #include <apti18n.h> /*}}}*/ @@ -47,7 +44,7 @@ using namespace std; // --------------------------------------------------------------------- /* */ pkgAcquire::Worker::Worker(Queue *Q,MethodConfig *Cnf, - pkgAcquireStatus *Log) : Log(Log) + pkgAcquireStatus *log) : d(NULL), Log(log) { OwnerQ = Q; Config = Cnf; @@ -55,23 +52,18 @@ pkgAcquire::Worker::Worker(Queue *Q,MethodConfig *Cnf, CurrentItem = 0; TotalSize = 0; CurrentSize = 0; - - Construct(); + + Construct(); } /*}}}*/ // Worker::Worker - Constructor for method config startup /*{{{*/ // --------------------------------------------------------------------- /* */ -pkgAcquire::Worker::Worker(MethodConfig *Cnf) +pkgAcquire::Worker::Worker(MethodConfig *Cnf) : d(NULL), OwnerQ(NULL), Config(Cnf), + Access(Cnf->Access), CurrentItem(NULL), + CurrentSize(0), TotalSize(0) { - OwnerQ = 0; - Config = Cnf; - Access = Cnf->Access; - CurrentItem = 0; - TotalSize = 0; - CurrentSize = 0; - - Construct(); + Construct(); } /*}}}*/ // Worker::Construct - Constructor helper /*{{{*/ @@ -136,7 +128,7 @@ bool pkgAcquire::Worker::Start() } for (int I = 0; I != 4; I++) SetCloseExec(Pipes[I],true); - + // Fork off the process Process = ExecFork(); if (Process == 0) @@ -145,9 +137,9 @@ bool pkgAcquire::Worker::Start() dup2(Pipes[1],STDOUT_FILENO); dup2(Pipes[2],STDIN_FILENO); SetCloseExec(STDOUT_FILENO,false); - SetCloseExec(STDIN_FILENO,false); + SetCloseExec(STDIN_FILENO,false); SetCloseExec(STDERR_FILENO,false); - + const char *Args[2]; Args[0] = Method.c_str(); Args[1] = 0; @@ -165,7 +157,7 @@ bool pkgAcquire::Worker::Start() close(Pipes[2]); OutReady = false; InReady = true; - + // Read the configuration data if (WaitFd(InFd) == false || ReadMessages() == false) @@ -174,7 +166,7 @@ bool pkgAcquire::Worker::Start() RunMessages(); if (OwnerQ != 0) SendConfiguration(); - + return true; } /*}}}*/ @@ -201,7 +193,7 @@ bool pkgAcquire::Worker::RunMessages() if (Debug == true) clog << " <- " << Access << ':' << QuoteString(Message,"\n") << endl; - + // Fetch the message number char *End; int Number = strtol(Message.c_str(),&End,10); @@ -209,21 +201,24 @@ bool pkgAcquire::Worker::RunMessages() return _error->Error("Invalid message from method %s: %s",Access.c_str(),Message.c_str()); string URI = LookupTag(Message,"URI"); - pkgAcquire::Queue::QItem *Itm = 0; + pkgAcquire::Queue::QItem *Itm = NULL; if (URI.empty() == false) Itm = OwnerQ->FindItem(URI,this); - // update used mirror - string UsedMirror = LookupTag(Message,"UsedMirror", ""); - if (!UsedMirror.empty() && - Itm && - Itm->Description.find(" ") != string::npos) + if (Itm != NULL) { - Itm->Description.replace(0, Itm->Description.find(" "), UsedMirror); - // FIXME: will we need this as well? - //Itm->ShortDesc = UsedMirror; + // update used mirror + string UsedMirror = LookupTag(Message,"UsedMirror", ""); + if (UsedMirror.empty() == false) + { + for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O) + (*O)->UsedMirror = UsedMirror; + + if (Itm->Description.find(" ") != string::npos) + Itm->Description.replace(0, Itm->Description.find(" "), UsedMirror); + } } - + // Determine the message number and dispatch switch (Number) { @@ -232,18 +227,18 @@ bool pkgAcquire::Worker::RunMessages() if (Capabilities(Message) == false) return _error->Error("Unable to process Capabilities message from %s",Access.c_str()); break; - + // 101 Log case 101: if (Debug == true) clog << " <- (log) " << LookupTag(Message,"Message") << endl; break; - + // 102 Status case 102: Status = LookupTag(Message,"Message"); break; - + // 103 Redirect case 103: { @@ -252,27 +247,49 @@ bool pkgAcquire::Worker::RunMessages() _error->Error("Method gave invalid 103 Redirect message"); break; } - - string NewURI = LookupTag(Message,"New-URI",URI.c_str()); + + std::string const NewURI = LookupTag(Message,"New-URI",URI.c_str()); Itm->URI = NewURI; ItemDone(); - pkgAcquire::Item *Owner = Itm->Owner; - pkgAcquire::ItemDesc Desc = *Itm; - // Change the status so that it can be dequeued - Owner->Status = pkgAcquire::Item::StatIdle; + for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O) + (*O)->Status = pkgAcquire::Item::StatIdle; // Mark the item as done (taking care of all queues) // and then put it in the main queue again + std::vector<Item*> const ItmOwners = Itm->Owners; OwnerQ->ItemDone(Itm); - OwnerQ->Owner->Enqueue(Desc); - - if (Log != 0) - Log->Done(Desc); + Itm = NULL; + for (pkgAcquire::Queue::QItem::owner_iterator O = ItmOwners.begin(); O != ItmOwners.end(); ++O) + { + pkgAcquire::Item *Owner = *O; + pkgAcquire::ItemDesc &desc = Owner->GetItemDesc(); + // if we change site, treat it as a mirror change + if (URI::SiteOnly(NewURI) != URI::SiteOnly(desc.URI)) + { + std::string const OldSite = desc.Description.substr(0, desc.Description.find(" ")); + if (likely(APT::String::Startswith(desc.URI, OldSite))) + { + std::string const OldExtra = desc.URI.substr(OldSite.length() + 1); + if (likely(APT::String::Endswith(NewURI, OldExtra))) + { + std::string const NewSite = NewURI.substr(0, NewURI.length() - OldExtra.length()); + Owner->UsedMirror = URI::ArchiveOnly(NewSite); + if (desc.Description.find(" ") != string::npos) + desc.Description.replace(0, desc.Description.find(" "), Owner->UsedMirror); + } + } + } + desc.URI = NewURI; + OwnerQ->Owner->Enqueue(desc); + + if (Log != 0) + Log->Done(desc); + } break; } - + // 200 URI Start case 200: { @@ -281,23 +298,27 @@ bool pkgAcquire::Worker::RunMessages() _error->Error("Method gave invalid 200 URI Start message"); break; } - + CurrentItem = Itm; CurrentSize = 0; TotalSize = strtoull(LookupTag(Message,"Size","0").c_str(), NULL, 10); ResumePoint = strtoull(LookupTag(Message,"Resume-Point","0").c_str(), NULL, 10); - Itm->Owner->Start(Message,strtoull(LookupTag(Message,"Size","0").c_str(), NULL, 10)); + for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O) + { + (*O)->Start(Message, TotalSize); - // Display update before completion - if (Log != 0 && Log->MorePulses == true) - Log->Pulse(Itm->Owner->GetOwner()); - - if (Log != 0) - Log->Fetch(*Itm); + // Display update before completion + if (Log != 0) + { + if (Log->MorePulses == true) + Log->Pulse((*O)->GetOwner()); + Log->Fetch((*O)->GetItemDesc()); + } + } break; } - + // 201 URI Done case 201: { @@ -306,72 +327,114 @@ bool pkgAcquire::Worker::RunMessages() _error->Error("Method gave invalid 201 URI Done message"); break; } - - pkgAcquire::Item *Owner = Itm->Owner; - pkgAcquire::ItemDesc Desc = *Itm; - if (RealFileExists(Owner->DestFile)) - ChangeOwnerAndPermissionOfFile("201::URIDone", Owner->DestFile.c_str(), "root", "root", 0644); + PrepareFiles("201::URIDone", Itm); // Display update before completion if (Log != 0 && Log->MorePulses == true) - Log->Pulse(Owner->GetOwner()); - - OwnerQ->ItemDone(Itm); - unsigned long long const ServerSize = strtoull(LookupTag(Message,"Size","0").c_str(), NULL, 10); - bool isHit = StringToBool(LookupTag(Message,"IMS-Hit"),false) || - StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false); - // Using the https method the server might return 200, but the - // If-Modified-Since condition is not satsified, libcurl will - // discard the download. In this case, however, TotalSize will be - // set to the actual size of the file, while ServerSize will be set - // to 0. Therefore, if the item is marked as a hit and the - // downloaded size (ServerSize) is 0, we ignore TotalSize. - if (TotalSize != 0 && (!isHit || ServerSize != 0) && ServerSize != TotalSize) - _error->Warning("Size of file %s is not what the server reported %s %llu", - Owner->DestFile.c_str(), LookupTag(Message,"Size","0").c_str(),TotalSize); - - // see if there is a hash to verify + for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O) + Log->Pulse((*O)->GetOwner()); + + std::string const filename = LookupTag(Message, "Filename", Itm->Owner->DestFile.c_str()); HashStringList ReceivedHashes; - 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) - ReceivedHashes.push_back(HashString(*type, hashsum)); + // see if we got hashes to verify + 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) + ReceivedHashes.push_back(HashString(*type, hashsum)); + } + // not all methods always sent Hashes our way + if (ReceivedHashes.usable() == false) + { + HashStringList const ExpectedHashes = Itm->GetExpectedHashes(); + if (ExpectedHashes.usable() == true && RealFileExists(filename)) + { + Hashes calc(ExpectedHashes); + FileFd file(filename, FileFd::ReadOnly, FileFd::None); + calc.AddFD(file); + ReceivedHashes = calc.GetHashStringList(); + } + } } - if(_config->FindB("Debug::pkgAcquire::Auth", false) == true) - { - std::clog << "201 URI Done: " << Owner->DescURI() << endl - << "ReceivedHash:" << endl; - for (HashStringList::const_iterator hs = ReceivedHashes.begin(); hs != ReceivedHashes.end(); ++hs) - std::clog << "\t- " << hs->toStr() << std::endl; - std::clog << "ExpectedHash:" << endl; - HashStringList expectedHashes = Owner->HashSums(); - for (HashStringList::const_iterator hs = expectedHashes.begin(); hs != expectedHashes.end(); ++hs) - std::clog << "\t- " << hs->toStr() << std::endl; - std::clog << endl; - } - Owner->Done(Message, ServerSize, ReceivedHashes, Config); - ItemDone(); + // only local files can refer other filenames and counting them as fetched would be unfair + if (Log != NULL && filename != Itm->Owner->DestFile) + Log->Fetched(ReceivedHashes.FileSize(),atoi(LookupTag(Message,"Resume-Point","0").c_str())); + + std::vector<Item*> const ItmOwners = Itm->Owners; + OwnerQ->ItemDone(Itm); + Itm = NULL; - // Log that we are done - if (Log != 0) + bool const isIMSHit = StringToBool(LookupTag(Message,"IMS-Hit"),false) || + StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false); + for (pkgAcquire::Queue::QItem::owner_iterator O = ItmOwners.begin(); O != ItmOwners.end(); ++O) { - if (isHit) + pkgAcquire::Item * const Owner = *O; + HashStringList const ExpectedHashes = Owner->GetExpectedHashes(); + if(_config->FindB("Debug::pkgAcquire::Auth", false) == true) + { + std::clog << "201 URI Done: " << Owner->DescURI() << endl + << "ReceivedHash:" << endl; + for (HashStringList::const_iterator hs = ReceivedHashes.begin(); hs != ReceivedHashes.end(); ++hs) + std::clog << "\t- " << hs->toStr() << std::endl; + std::clog << "ExpectedHash:" << endl; + for (HashStringList::const_iterator hs = ExpectedHashes.begin(); hs != ExpectedHashes.end(); ++hs) + std::clog << "\t- " << hs->toStr() << std::endl; + std::clog << endl; + } + + // decide if what we got is what we expected + bool consideredOkay = false; + if (ExpectedHashes.usable()) { - /* Hide 'hits' for local only sources - we also manage to - hide gets */ - if (Config->LocalOnly == false) - Log->IMSHit(Desc); - } + if (ReceivedHashes.usable() == false) + { + /* IMS-Hits can't be checked here as we will have uncompressed file, + but the hashes for the compressed file. What we have was good through + so all we have to ensure later is that we are not stalled. */ + consideredOkay = isIMSHit; + } + else if (ReceivedHashes == ExpectedHashes) + consideredOkay = true; + else + consideredOkay = false; + + } + else if (Owner->HashesRequired() == true) + consideredOkay = false; else - Log->Done(Desc); + consideredOkay = true; + + if (consideredOkay == true) + consideredOkay = Owner->VerifyDone(Message, Config); + else // hashsum mismatch + Owner->Status = pkgAcquire::Item::StatAuthError; + + if (consideredOkay == true) + { + Owner->Done(Message, ReceivedHashes, Config); + if (Log != 0) + { + if (isIMSHit) + Log->IMSHit(Owner->GetItemDesc()); + else + Log->Done(Owner->GetItemDesc()); + } + } + else + { + Owner->Failed(Message,Config); + if (Log != 0) + Log->Fail(Owner->GetItemDesc()); + } } + ItemDone(); break; - } - + } + // 400 URI Failure case 400: { @@ -382,44 +445,46 @@ bool pkgAcquire::Worker::RunMessages() break; } + PrepareFiles("400::URIFailure", Itm); + // Display update before completion if (Log != 0 && Log->MorePulses == true) - Log->Pulse(Itm->Owner->GetOwner()); - - pkgAcquire::Item *Owner = Itm->Owner; - pkgAcquire::ItemDesc Desc = *Itm; - - if (RealFileExists(Owner->DestFile)) - ChangeOwnerAndPermissionOfFile("400::URIFailure", Owner->DestFile.c_str(), "root", "root", 0644); + for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O) + Log->Pulse((*O)->GetOwner()); + std::vector<Item*> const ItmOwners = Itm->Owners; OwnerQ->ItemDone(Itm); + Itm = NULL; - // set some status - if(LookupTag(Message,"FailReason") == "Timeout" || - LookupTag(Message,"FailReason") == "TmpResolveFailure" || - LookupTag(Message,"FailReason") == "ResolveFailure" || - LookupTag(Message,"FailReason") == "ConnectionRefused") - Owner->Status = pkgAcquire::Item::StatTransientNetworkError; + for (pkgAcquire::Queue::QItem::owner_iterator O = ItmOwners.begin(); O != ItmOwners.end(); ++O) + { + // set some status + if(LookupTag(Message,"FailReason") == "Timeout" || + LookupTag(Message,"FailReason") == "TmpResolveFailure" || + LookupTag(Message,"FailReason") == "ResolveFailure" || + LookupTag(Message,"FailReason") == "ConnectionRefused") + (*O)->Status = pkgAcquire::Item::StatTransientNetworkError; - Owner->Failed(Message,Config); - ItemDone(); + (*O)->Failed(Message,Config); - if (Log != 0) - Log->Fail(Desc); + if (Log != 0) + Log->Fail((*O)->GetItemDesc()); + } + ItemDone(); break; - } - + } + // 401 General Failure case 401: _error->Error("Method %s General failure: %s",Access.c_str(),LookupTag(Message,"Message").c_str()); break; - + // 403 Media Change case 403: - MediaChange(Message); + MediaChange(Message); break; - } + } } return true; } @@ -432,7 +497,7 @@ bool pkgAcquire::Worker::Capabilities(string Message) { if (Config == 0) return true; - + Config->Version = LookupTag(Message,"Version"); Config->SingleInstance = StringToBool(LookupTag(Message,"Single-Instance"),false); Config->Pipeline = StringToBool(LookupTag(Message,"Pipeline"),false); @@ -447,13 +512,13 @@ bool pkgAcquire::Worker::Capabilities(string Message) clog << "Configured access method " << Config->Access << endl; clog << "Version:" << Config->Version << " SingleInstance:" << Config->SingleInstance << - " Pipeline:" << Config->Pipeline << - " SendConfig:" << Config->SendConfig << - " LocalOnly: " << Config->LocalOnly << - " NeedsCleanup: " << Config->NeedsCleanup << + " Pipeline:" << Config->Pipeline << + " SendConfig:" << Config->SendConfig << + " LocalOnly: " << Config->LocalOnly << + " NeedsCleanup: " << Config->NeedsCleanup << " Removable: " << Config->Removable << endl; } - + return true; } /*}}}*/ @@ -463,14 +528,14 @@ bool pkgAcquire::Worker::Capabilities(string Message) bool pkgAcquire::Worker::MediaChange(string Message) { int status_fd = _config->FindI("APT::Status-Fd",-1); - if(status_fd > 0) + if(status_fd > 0) { string Media = LookupTag(Message,"Media"); - string Drive = LookupTag(Message,"Drive"); + string Drive = LookupTag(Message,"Drive"); ostringstream msg,status; ioprintf(msg,_("Please insert the disc labeled: " "'%s' " - "in the drive '%s' and press enter."), + "in the drive '%s' and press [Enter]."), Media.c_str(),Drive.c_str()); status << "media-change: " // message << Media << ":" // media @@ -536,21 +601,29 @@ bool pkgAcquire::Worker::QueueItem(pkgAcquire::Queue::QItem *Item) { if (OutFd == -1) return false; - + string Message = "600 URI Acquire\n"; Message.reserve(300); Message += "URI: " + Item->URI; Message += "\nFilename: " + Item->Owner->DestFile; - HashStringList const hsl = Item->Owner->HashSums(); + + HashStringList const hsl = Item->GetExpectedHashes(); for (HashStringList::const_iterator hs = hsl.begin(); hs != hsl.end(); ++hs) Message += "\nExpected-" + hs->HashType() + ": " + hs->HashValue(); - if(Item->Owner->FileSize > 0) + + if (hsl.FileSize() == 0) { - string MaximumSize; - strprintf(MaximumSize, "%llu", Item->Owner->FileSize); - Message += "\nMaximum-Size: " + MaximumSize; + unsigned long long FileSize = Item->GetMaximumSize(); + if(FileSize > 0) + { + string MaximumSize; + strprintf(MaximumSize, "%llu", FileSize); + Message += "\nMaximum-Size: " + MaximumSize; + } } - Message += Item->Owner->Custom600Headers(); + + Item->SyncDestinationFiles(); + Message += Item->Custom600Headers(); Message += "\n\n"; if (RealFileExists(Item->Owner->DestFile)) @@ -564,7 +637,7 @@ bool pkgAcquire::Worker::QueueItem(pkgAcquire::Queue::QItem *Item) clog << " -> " << Access << ':' << QuoteString(Message,"\n") << endl; OutQueue += Message; OutReady = true; - + return true; } /*}}}*/ @@ -586,7 +659,7 @@ bool pkgAcquire::Worker::OutFdReady() OutQueue.erase(0,Res); if (OutQueue.empty() == true) OutReady = false; - + return true; } /*}}}*/ @@ -608,7 +681,7 @@ bool pkgAcquire::Worker::InFdReady() bool pkgAcquire::Worker::MethodFailure() { _error->Error("Method %s has died unexpectedly!",Access.c_str()); - + // do not reap the child here to show meaningfull error to the user ExecWait(Process,Access.c_str(),false); Process = -1; @@ -620,26 +693,22 @@ bool pkgAcquire::Worker::MethodFailure() InReady = false; OutQueue = string(); MessageQueue.erase(MessageQueue.begin(),MessageQueue.end()); - + return false; } /*}}}*/ -// Worker::Pulse - Called periodically /*{{{*/ +// Worker::Pulse - Called periodically /*{{{*/ // --------------------------------------------------------------------- /* */ void pkgAcquire::Worker::Pulse() { if (CurrentItem == 0) return; - + struct stat Buf; if (stat(CurrentItem->Owner->DestFile.c_str(),&Buf) != 0) return; CurrentSize = Buf.st_size; - - // Hmm? Should not happen... - if (CurrentSize > TotalSize && TotalSize != 0) - TotalSize = CurrentSize; } /*}}}*/ // Worker::ItemDone - Called when the current item is finished /*{{{*/ @@ -653,3 +722,33 @@ void pkgAcquire::Worker::ItemDone() Status = string(); } /*}}}*/ +void pkgAcquire::Worker::PrepareFiles(char const * const caller, pkgAcquire::Queue::QItem const * const Itm)/*{{{*/ +{ + if (RealFileExists(Itm->Owner->DestFile)) + { + ChangeOwnerAndPermissionOfFile(caller, Itm->Owner->DestFile.c_str(), "root", "root", 0644); + std::string const filename = Itm->Owner->DestFile; + for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O) + { + pkgAcquire::Item const * const Owner = *O; + if (Owner->DestFile == filename) + continue; + unlink(Owner->DestFile.c_str()); + if (link(filename.c_str(), Owner->DestFile.c_str()) != 0) + { + // different mounts can't happen for us as we download to lists/ by default, + // but if the system is reused by others the locations can potentially be on + // different disks, so use symlink as poor-men replacement. + // FIXME: Real copying as last fallback, but that is costly, so offload to a method preferable + if (symlink(filename.c_str(), Owner->DestFile.c_str()) != 0) + _error->Error("Can't create (sym)link of file %s to %s", filename.c_str(), Owner->DestFile.c_str()); + } + } + } + else + { + for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O) + unlink((*O)->DestFile.c_str()); + } +} + /*}}}*/ diff --git a/apt-pkg/acquire-worker.h b/apt-pkg/acquire-worker.h index db8889c8e..42762abe0 100644 --- a/apt-pkg/acquire-worker.h +++ b/apt-pkg/acquire-worker.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: acquire-worker.h,v 1.12 2001/02/20 07:03:17 jgg Exp $ /* ###################################################################### Acquire Worker - Worker process manager @@ -48,7 +47,7 @@ class pkgAcquire::Worker : public WeakPointable { /** \brief dpointer placeholder (for later in case we need it) */ - void *d; + void * const d; friend class pkgAcquire; @@ -318,7 +317,7 @@ class pkgAcquire::Worker : public WeakPointable * \param Config A location in which to store information about * the fetch method. */ - Worker(MethodConfig *Config); + explicit Worker(MethodConfig *Config); /** \brief Clean up this worker. * @@ -326,6 +325,9 @@ class pkgAcquire::Worker : public WeakPointable * \b false, also rudely interrupts the worker with a SIGINT. */ virtual ~Worker(); + +private: + APT_HIDDEN void PrepareFiles(char const * const caller, pkgAcquire::Queue::QItem const * const Itm); }; /** @} */ diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc index 0c815c005..f8b077367 100644 --- a/apt-pkg/acquire.cc +++ b/apt-pkg/acquire.cc @@ -23,6 +23,7 @@ #include <apt-pkg/strutl.h> #include <apt-pkg/fileutl.h> +#include <algorithm> #include <string> #include <vector> #include <iostream> @@ -40,7 +41,6 @@ #include <sys/select.h> #include <errno.h> #include <sys/stat.h> -#include <sys/types.h> #include <apti18n.h> /*}}}*/ @@ -50,13 +50,13 @@ using namespace std; // Acquire::pkgAcquire - Constructor /*{{{*/ // --------------------------------------------------------------------- /* We grab some runtime state from the configuration space */ -pkgAcquire::pkgAcquire() : LockFD(-1), Queues(0), Workers(0), Configs(0), Log(NULL), ToFetch(0), +pkgAcquire::pkgAcquire() : LockFD(-1), d(NULL), Queues(0), Workers(0), Configs(0), Log(NULL), ToFetch(0), Debug(_config->FindB("Debug::pkgAcquire",false)), Running(false) { Initialize(); } -pkgAcquire::pkgAcquire(pkgAcquireStatus *Progress) : LockFD(-1), Queues(0), Workers(0), +pkgAcquire::pkgAcquire(pkgAcquireStatus *Progress) : LockFD(-1), d(NULL), Queues(0), Workers(0), Configs(0), Log(NULL), ToFetch(0), Debug(_config->FindB("Debug::pkgAcquire",false)), Running(false) @@ -652,8 +652,8 @@ pkgAcquire::MethodConfig::MethodConfig() : d(NULL), Next(0), SingleInstance(fals // Queue::Queue - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ -pkgAcquire::Queue::Queue(string Name,pkgAcquire *Owner) : d(NULL), Next(0), - Name(Name), Items(0), Workers(0), Owner(Owner), PipeDepth(0), MaxPipeDepth(1) +pkgAcquire::Queue::Queue(string const &name,pkgAcquire * const owner) : d(NULL), Next(0), + Name(name), Items(0), Workers(0), Owner(owner), PipeDepth(0), MaxPipeDepth(1) { } /*}}}*/ @@ -679,10 +679,14 @@ bool pkgAcquire::Queue::Enqueue(ItemDesc &Item) { QItem **I = &Items; // move to the end of the queue and check for duplicates here + HashStringList const hsl = Item.Owner->GetExpectedHashes(); for (; *I != 0; I = &(*I)->Next) - if (Item.URI == (*I)->URI) + if (Item.URI == (*I)->URI || hsl == (*I)->Owner->GetExpectedHashes()) { - Item.Owner->Status = Item::StatDone; + if (_config->FindB("Debug::pkgAcquire::Worker",false) == true) + std::cerr << " @ Queue: Action combined for " << Item.URI << " and " << (*I)->URI << std::endl; + (*I)->Owners.push_back(Item.Owner); + Item.Owner->Status = (*I)->Owner->Status; return false; } @@ -705,13 +709,13 @@ bool pkgAcquire::Queue::Dequeue(Item *Owner) { if (Owner->Status == pkgAcquire::Item::StatFetching) return _error->Error("Tried to dequeue a fetching object"); - + bool Res = false; - + QItem **I = &Items; for (; *I != 0;) { - if ((*I)->Owner == Owner) + if (Owner == (*I)->Owner) { QItem *Jnk= *I; *I = (*I)->Next; @@ -722,7 +726,7 @@ bool pkgAcquire::Queue::Dequeue(Item *Owner) else I = &(*I)->Next; } - + return Res; } /*}}}*/ @@ -799,9 +803,12 @@ pkgAcquire::Queue::QItem *pkgAcquire::Queue::FindItem(string URI,pkgAcquire::Wor bool pkgAcquire::Queue::ItemDone(QItem *Itm) { PipeDepth--; - if (Itm->Owner->Status == pkgAcquire::Item::StatFetching) - Itm->Owner->Status = pkgAcquire::Item::StatDone; - + for (QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O) + { + if ((*O)->Status == pkgAcquire::Item::StatFetching) + (*O)->Status = pkgAcquire::Item::StatDone; + } + if (Itm->Owner->QueueCounter <= 1) Owner->Dequeue(Itm->Owner); else @@ -809,7 +816,7 @@ bool pkgAcquire::Queue::ItemDone(QItem *Itm) Dequeue(Itm->Owner); Owner->Bump(); } - + return Cycle(); } /*}}}*/ @@ -824,7 +831,7 @@ bool pkgAcquire::Queue::Cycle() if (PipeDepth < 0) return _error->Error("Pipedepth failure"); - + // Look for a queable item QItem *I = Items; while (PipeDepth < (signed)MaxPipeDepth) @@ -832,18 +839,19 @@ bool pkgAcquire::Queue::Cycle() for (; I != 0; I = I->Next) if (I->Owner->Status == pkgAcquire::Item::StatIdle) break; - + // Nothing to do, queue is idle. if (I == 0) return true; - + I->Worker = Workers; - I->Owner->Status = pkgAcquire::Item::StatFetching; + for (QItem::owner_iterator O = I->Owners.begin(); O != I->Owners.end(); ++O) + (*O)->Status = pkgAcquire::Item::StatFetching; PipeDepth++; if (Workers->QueueItem(I) == false) return false; } - + return true; } /*}}}*/ @@ -855,10 +863,98 @@ void pkgAcquire::Queue::Bump() Cycle(); } /*}}}*/ +HashStringList pkgAcquire::Queue::QItem::GetExpectedHashes() const /*{{{*/ +{ + /* each Item can have multiple owners and each owner might have different + hashes, even if that is unlikely in practice and if so at least some + owners will later fail. There is one situation through which is not a + failure and still needs this handling: Two owners who expect the same + file, but one owner only knows the SHA1 while the other only knows SHA256. */ + HashStringList superhsl; + for (pkgAcquire::Queue::QItem::owner_iterator O = Owners.begin(); O != Owners.end(); ++O) + { + HashStringList const hsl = (*O)->GetExpectedHashes(); + if (hsl.usable() == false) + continue; + if (superhsl.usable() == false) + superhsl = hsl; + else + { + // we merge both lists - if we find disagreement send no hashes + HashStringList::const_iterator hs = hsl.begin(); + for (; hs != hsl.end(); ++hs) + if (superhsl.push_back(*hs) == false) + break; + if (hs != hsl.end()) + { + superhsl.clear(); + break; + } + } + } + return superhsl; +} + /*}}}*/ +APT_PURE unsigned long long pkgAcquire::Queue::QItem::GetMaximumSize() const /*{{{*/ +{ + unsigned long long Maximum = std::numeric_limits<unsigned long long>::max(); + for (pkgAcquire::Queue::QItem::owner_iterator O = Owners.begin(); O != Owners.end(); ++O) + { + if ((*O)->FileSize == 0) + continue; + Maximum = std::min(Maximum, (*O)->FileSize); + } + if (Maximum == std::numeric_limits<unsigned long long>::max()) + return 0; + return Maximum; +} + /*}}}*/ +void pkgAcquire::Queue::QItem::SyncDestinationFiles() const /*{{{*/ +{ + /* ensure that the first owner has the best partial file of all and + the rest have (potentially dangling) symlinks to it so that + everything (like progress reporting) finds it easily */ + std::string superfile = Owner->DestFile; + off_t supersize = 0; + for (pkgAcquire::Queue::QItem::owner_iterator O = Owners.begin(); O != Owners.end(); ++O) + { + if ((*O)->DestFile == superfile) + continue; + struct stat file; + if (lstat((*O)->DestFile.c_str(),&file) == 0) + { + if ((file.st_mode & S_IFREG) == 0) + unlink((*O)->DestFile.c_str()); + else if (supersize < file.st_size) + { + supersize = file.st_size; + unlink(superfile.c_str()); + rename((*O)->DestFile.c_str(), superfile.c_str()); + } + else + unlink((*O)->DestFile.c_str()); + if (symlink(superfile.c_str(), (*O)->DestFile.c_str()) != 0) + { + ; // not a problem per-se and no real alternative + } + } + } +} + /*}}}*/ +std::string pkgAcquire::Queue::QItem::Custom600Headers() const /*{{{*/ +{ + /* The others are relatively easy to merge, but this one? + Lets not merge and see how far we can run with it… + Likely, nobody will ever notice as all the items will + be of the same class and hence generate the same headers. */ + return Owner->Custom600Headers(); +} + /*}}}*/ + // AcquireStatus::pkgAcquireStatus - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ -pkgAcquireStatus::pkgAcquireStatus() : d(NULL), Percent(0), Update(true), MorePulses(false) +pkgAcquireStatus::pkgAcquireStatus() : d(NULL), Percent(-1), Update(true), MorePulses(false) { Start(); } @@ -914,9 +1010,9 @@ bool pkgAcquireStatus::Pulse(pkgAcquire *Owner) { CurrentBytes += I->CurrentSize; ResumeSize += I->ResumePoint; - + // Files with unknown size always have 100% completion - if (I->CurrentItem->Owner->FileSize == 0 && + if (I->CurrentItem->Owner->FileSize == 0 && I->CurrentItem->Owner->Complete == false) TotalBytes += I->CurrentSize; } @@ -957,13 +1053,17 @@ bool pkgAcquireStatus::Pulse(pkgAcquire *Owner) Time = NewTime; } + double const OldPercent = Percent; // calculate the percentage, if we have too little data assume 1% if (TotalBytes > 0 && UnfetchedReleaseFiles) Percent = 0; - else + else // use both files and bytes because bytes can be unreliable - Percent = (0.8 * (CurrentBytes/float(TotalBytes)*100.0) + + Percent = (0.8 * (CurrentBytes/float(TotalBytes)*100.0) + 0.2 * (CurrentItems/float(TotalItems)*100.0)); + double const DiffPercent = Percent - OldPercent; + if (DiffPercent < 0.001 && _config->FindB("Acquire::Progress::Diffpercent", false) == true) + return true; int fd = _config->FindI("APT::Status-Fd",-1); if(fd > 0) @@ -981,11 +1081,11 @@ bool pkgAcquireStatus::Pulse(pkgAcquire *Owner) snprintf(msg,sizeof(msg), _("Retrieving file %li of %li (%s remaining)"), i, TotalItems, TimeToStr(ETA).c_str()); else snprintf(msg,sizeof(msg), _("Retrieving file %li of %li"), i, TotalItems); - + // build the status str status << "dlstatus:" << i << ":" << std::setprecision(3) << Percent - << ":" << msg + << ":" << msg << endl; std::string const dlstatus = status.str(); @@ -1042,6 +1142,15 @@ void pkgAcquireStatus::Fetched(unsigned long long Size,unsigned long long Resume } /*}}}*/ +pkgAcquire::UriIterator::UriIterator(pkgAcquire::Queue *Q) : d(NULL), CurQ(Q), CurItem(0) +{ + while (CurItem == 0 && CurQ != 0) + { + CurItem = CurQ->Items; + CurQ = CurQ->Next; + } +} + APT_CONST pkgAcquire::UriIterator::~UriIterator() {} APT_CONST pkgAcquire::MethodConfig::~MethodConfig() {} APT_CONST pkgAcquireStatus::~pkgAcquireStatus() {} diff --git a/apt-pkg/acquire.h b/apt-pkg/acquire.h index fc90624e1..0d2b21233 100644 --- a/apt-pkg/acquire.h +++ b/apt-pkg/acquire.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: acquire.h,v 1.29.2.1 2003/12/24 23:09:17 mdz Exp $ /* ###################################################################### Acquire - File Acquiration @@ -68,9 +67,10 @@ #include <apt-pkg/macros.h> #include <apt-pkg/weakptr.h> +#include <apt-pkg/hashes.h> -#include <vector> #include <string> +#include <vector> #include <stddef.h> #include <sys/time.h> @@ -101,7 +101,7 @@ class pkgAcquire /** \brief FD of the Lock file we acquire in Setup (if any) */ int LockFD; /** \brief dpointer placeholder (for later in case we need it) */ - void *d; + void * const d; public: @@ -369,7 +369,7 @@ class pkgAcquire bool GetLock(std::string const &Lock); /** \brief Construct a new pkgAcquire. */ - pkgAcquire(pkgAcquireStatus *Log); + explicit pkgAcquire(pkgAcquireStatus *Log); pkgAcquire(); /** \brief Destroy this pkgAcquire object. @@ -390,13 +390,13 @@ class pkgAcquire */ struct pkgAcquire::ItemDesc : public WeakPointable { - /** \brief The URI from which to download this item. */ + /** \brief URI from which to download this item. */ std::string URI; - /** brief A description of this item. */ + /** \brief description of this item. */ std::string Description; - /** brief A shorter description of this item. */ + /** \brief shorter description of this item. */ std::string ShortDesc; - /** brief The underlying item which is to be downloaded. */ + /** \brief underlying item which is to be downloaded. */ Item *Owner; }; /*}}}*/ @@ -411,7 +411,7 @@ class pkgAcquire::Queue friend class pkgAcquire::Worker; /** \brief dpointer placeholder (for later in case we need it) */ - void *d; + void * const d; /** \brief The next queue in the pkgAcquire object's list of queues. */ Queue *Next; @@ -419,13 +419,18 @@ class pkgAcquire::Queue protected: /** \brief A single item placed in this queue. */ - struct QItem : pkgAcquire::ItemDesc + struct QItem : public ItemDesc { /** \brief The next item in the queue. */ QItem *Next; /** \brief The worker associated with this item, if any. */ pkgAcquire::Worker *Worker; + /** \brief The underlying items interested in the download */ + std::vector<Item*> Owners; + + typedef std::vector<Item*>::const_iterator owner_iterator; + /** \brief Assign the ItemDesc portion of this QItem from * another ItemDesc */ @@ -434,10 +439,24 @@ class pkgAcquire::Queue URI = I.URI; Description = I.Description; ShortDesc = I.ShortDesc; + Owners.clear(); + Owners.push_back(I.Owner); Owner = I.Owner; }; + + /** @return the sum of all expected hashes by all owners */ + HashStringList GetExpectedHashes() const; + + /** @return smallest maximum size of all owners */ + unsigned long long GetMaximumSize() const; + + /** \brief get partial files in order */ + void SyncDestinationFiles() const; + + /** @return the custom headers to use for this item */ + std::string Custom600Headers() const; }; - + /** \brief The name of this queue. */ std::string Name; @@ -557,7 +576,7 @@ class pkgAcquire::Queue * \param Name The name of the new queue. * \param Owner The download process that owns the new queue. */ - Queue(std::string Name,pkgAcquire *Owner); + Queue(std::string const &Name,pkgAcquire * const Owner); /** Shut down all the worker processes associated with this queue * and empty the queue. @@ -569,7 +588,7 @@ class pkgAcquire::Queue class pkgAcquire::UriIterator { /** \brief dpointer placeholder (for later in case we need it) */ - void *d; + void * const d; /** The next queue to iterate over. */ pkgAcquire::Queue *CurQ; @@ -590,7 +609,7 @@ class pkgAcquire::UriIterator } }; - inline pkgAcquire::ItemDesc const *operator ->() const {return CurItem;}; + inline pkgAcquire::Queue::QItem const *operator ->() const {return CurItem;}; inline bool operator !=(UriIterator const &rhs) const {return rhs.CurQ != CurQ || rhs.CurItem != CurItem;}; inline bool operator ==(UriIterator const &rhs) const {return rhs.CurQ == CurQ && rhs.CurItem == CurItem;}; @@ -598,14 +617,7 @@ class pkgAcquire::UriIterator * * \param Q The queue over which this UriIterator should iterate. */ - UriIterator(pkgAcquire::Queue *Q) : d(NULL), CurQ(Q), CurItem(0) - { - while (CurItem == 0 && CurQ != 0) - { - CurItem = CurQ->Items; - CurQ = CurQ->Next; - } - } + explicit UriIterator(pkgAcquire::Queue *Q); virtual ~UriIterator(); }; /*}}}*/ @@ -613,7 +625,7 @@ class pkgAcquire::UriIterator struct pkgAcquire::MethodConfig { /** \brief dpointer placeholder (for later in case we need it) */ - void *d; + void * const d; /** \brief The next link on the acquire method list. * @@ -674,7 +686,7 @@ struct pkgAcquire::MethodConfig class pkgAcquireStatus { /** \brief dpointer placeholder (for later in case we need it) */ - void *d; + void * const d; protected: diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index adbec82f7..6d982c551 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -19,9 +19,7 @@ #include <apt-pkg/algorithms.h> #include <apt-pkg/error.h> #include <apt-pkg/configuration.h> -#include <apt-pkg/sptr.h> #include <apt-pkg/edsp.h> -#include <apt-pkg/progress.h> #include <apt-pkg/depcache.h> #include <apt-pkg/packagemanager.h> #include <apt-pkg/pkgcache.h> @@ -43,7 +41,7 @@ pkgProblemResolver *pkgProblemResolver::This = 0; /* The legacy translations here of input Pkg iterators is obsolete, this is not necessary since the pkgCaches are fully shared now. */ pkgSimulate::pkgSimulate(pkgDepCache *Cache) : pkgPackageManager(Cache), - iPolicy(Cache), + d(NULL), iPolicy(Cache), Sim(&Cache->GetCache(),&iPolicy), group(Sim) { @@ -476,8 +474,8 @@ void pkgProblemResolver::MakeScores() } // Copy the scores to advoid additive looping - SPtrArray<int> OldScores = new int[Size]; - memcpy(OldScores,Scores,sizeof(*Scores)*Size); + std::unique_ptr<int[]> OldScores(new int[Size]); + memcpy(OldScores.get(),Scores,sizeof(*Scores)*Size); /* Now we cause 1 level of dependency inheritance, that is we add the score of the packages that depend on the target Package. This @@ -638,14 +636,6 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg) } /*}}}*/ // ProblemResolver::Resolve - calls a resolver to fix the situation /*{{{*/ -// --------------------------------------------------------------------- -/* */ -#if APT_PKG_ABI < 413 -bool pkgProblemResolver::Resolve(bool BrokenFix) -{ - return Resolve(BrokenFix, NULL); -} -#endif bool pkgProblemResolver::Resolve(bool BrokenFix, OpProgress * const Progress) { std::string const solver = _config->Find("APT::Solver", "internal"); @@ -710,17 +700,17 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) operates from highest score to lowest. This prevents problems when high score packages cause the removal of lower score packages that would cause the removal of even lower score packages. */ - SPtrArray<pkgCache::Package *> PList = new pkgCache::Package *[Size]; - pkgCache::Package **PEnd = PList; + std::unique_ptr<pkgCache::Package *[]> PList(new pkgCache::Package *[Size]); + pkgCache::Package **PEnd = PList.get(); for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) *PEnd++ = I; This = this; - qsort(PList,PEnd - PList,sizeof(*PList),&ScoreSort); + qsort(PList.get(),PEnd - PList.get(),sizeof(PList[0]),&ScoreSort); if (_config->FindB("Debug::pkgProblemResolver::ShowScores",false) == true) { clog << "Show Scores" << endl; - for (pkgCache::Package **K = PList; K != PEnd; K++) + for (pkgCache::Package **K = PList.get(); K != PEnd; K++) if (Scores[(*K)->ID] != 0) { pkgCache::PkgIterator Pkg(Cache,*K); @@ -742,7 +732,7 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) for (int Counter = 0; Counter != 10 && Change == true; Counter++) { Change = false; - for (pkgCache::Package **K = PList; K != PEnd; K++) + for (pkgCache::Package **K = PList.get(); K != PEnd; K++) { pkgCache::PkgIterator I(Cache,*K); @@ -853,8 +843,8 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) /* Look across the version list. If there are no possible targets then we keep the package and bail. This is necessary if a package has a dep on another package that can't be found */ - SPtrArray<pkgCache::Version *> VList = Start.AllTargets(); - if (*VList == 0 && (Flags[I->ID] & Protected) != Protected && + std::unique_ptr<pkgCache::Version *[]> VList(Start.AllTargets()); + if (VList[0] == 0 && (Flags[I->ID] & Protected) != Protected && Start.IsNegative() == false && Cache[I].NowBroken() == false) { @@ -871,7 +861,7 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) } bool Done = false; - for (pkgCache::Version **V = VList; *V != 0; V++) + for (pkgCache::Version **V = VList.get(); *V != 0; V++) { pkgCache::VerIterator Ver(Cache,*V); pkgCache::PkgIterator Pkg = Ver.ParentPkg(); @@ -1144,12 +1134,6 @@ bool pkgProblemResolver::InstOrNewPolicyBroken(pkgCache::PkgIterator I) /* This is the work horse of the soft upgrade routine. It is very gental in that it does not install or remove any packages. It is assumed that the system was non-broken previously. */ -#if APT_PKG_ABI < 413 -bool pkgProblemResolver::ResolveByKeep() -{ - return ResolveByKeep(NULL); -} -#endif bool pkgProblemResolver::ResolveByKeep(OpProgress * const Progress) { std::string const solver = _config->Find("APT::Solver", "internal"); @@ -1247,8 +1231,8 @@ bool pkgProblemResolver::ResolveByKeepInternal() clog << "Package " << I.FullName(false) << " " << Start << endl; // Look at all the possible provides on this package - SPtrArray<pkgCache::Version *> VList = Start.AllTargets(); - for (pkgCache::Version **V = VList; *V != 0; V++) + std::unique_ptr<pkgCache::Version *[]> VList(Start.AllTargets()); + for (pkgCache::Version **V = VList.get(); *V != 0; V++) { pkgCache::VerIterator Ver(Cache,*V); pkgCache::PkgIterator Pkg = Ver.ParentPkg(); diff --git a/apt-pkg/algorithms.h b/apt-pkg/algorithms.h index 2ac28c0d7..aad261b63 100644 --- a/apt-pkg/algorithms.h +++ b/apt-pkg/algorithms.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: algorithms.h,v 1.10 2001/05/22 04:17:41 jgg Exp $ /* ###################################################################### Algorithms - A set of misc algorithms @@ -55,6 +54,7 @@ using std::ostream; class pkgSimulate : public pkgPackageManager /*{{{*/ { + void * const d; protected: class Policy : public pkgDepCache::Policy @@ -62,12 +62,12 @@ class pkgSimulate : public pkgPackageManager /*{{{*/ pkgDepCache *Cache; public: - virtual VerIterator GetCandidateVer(PkgIterator const &Pkg) + virtual VerIterator GetCandidateVer(PkgIterator const &Pkg) APT_OVERRIDE { return (*Cache)[Pkg].CandidateVerIter(*Cache); } - Policy(pkgDepCache *Cache) : Cache(Cache) {}; + explicit Policy(pkgDepCache *Cache) : Cache(Cache) {}; }; unsigned char *Flags; @@ -77,9 +77,9 @@ class pkgSimulate : public pkgPackageManager /*{{{*/ pkgDepCache::ActionGroup group; // The Actuall installation implementation - virtual bool Install(PkgIterator Pkg,std::string File); - virtual bool Configure(PkgIterator Pkg); - virtual bool Remove(PkgIterator Pkg,bool Purge); + virtual bool Install(PkgIterator Pkg,std::string File) APT_OVERRIDE; + virtual bool Configure(PkgIterator Pkg) APT_OVERRIDE; + virtual bool Remove(PkgIterator Pkg,bool Purge) APT_OVERRIDE; private: APT_HIDDEN void ShortBreaks(); @@ -87,15 +87,15 @@ private: public: - pkgSimulate(pkgDepCache *Cache); - ~pkgSimulate(); + explicit pkgSimulate(pkgDepCache *Cache); + virtual ~pkgSimulate(); }; /*}}}*/ class pkgProblemResolver /*{{{*/ { private: /** \brief dpointer placeholder (for later in case we need it) */ - void *d; + void * const d; pkgDepCache &Cache; typedef pkgCache::PkgIterator PkgIterator; @@ -138,25 +138,15 @@ class pkgProblemResolver /*{{{*/ inline void Clear(pkgCache::PkgIterator Pkg) {Flags[Pkg->ID] &= ~(Protected | ToRemove);}; // Try to intelligently resolve problems by installing and removing packages -#if APT_PKG_ABI >= 413 bool Resolve(bool BrokenFix = false, OpProgress * const Progress = NULL); -#else - bool Resolve(bool BrokenFix = false); - bool Resolve(bool BrokenFix, OpProgress * const Progress); -#endif // Try to resolve problems only by using keep -#if APT_PKG_ABI >= 413 bool ResolveByKeep(OpProgress * const Progress = NULL); -#else - bool ResolveByKeep(); - bool ResolveByKeep(OpProgress * const Progress); -#endif APT_DEPRECATED void InstallProtect(); - pkgProblemResolver(pkgDepCache *Cache); - ~pkgProblemResolver(); + explicit pkgProblemResolver(pkgDepCache *Cache); + virtual ~pkgProblemResolver(); }; /*}}}*/ bool pkgApplyStatus(pkgDepCache &Cache); diff --git a/apt-pkg/aptconfiguration.cc b/apt-pkg/aptconfiguration.cc index 01b85a74e..f5bc18394 100644 --- a/apt-pkg/aptconfiguration.cc +++ b/apt-pkg/aptconfiguration.cc @@ -29,7 +29,6 @@ #include <string> #include <vector> -#include <apti18n.h> /*}}}*/ namespace APT { // setDefaultConfigurationForCompressors /*{{{*/ @@ -222,7 +221,7 @@ std::vector<std::string> const Configuration::getLanguages(bool const &All, // get the environment language codes: LC_MESSAGES (and later LANGUAGE) // we extract both, a long and a short code and then we will // check if we actually need both (rare) or if the short is enough - string const envMsg = string(Locale == 0 ? std::setlocale(LC_MESSAGES, NULL) : *Locale); + string const envMsg = string(Locale == 0 ? ::setlocale(LC_MESSAGES, NULL) : *Locale); size_t const lenShort = (envMsg.find('_') != string::npos) ? envMsg.find('_') : 2; size_t const lenLong = (envMsg.find_first_of(".@") != string::npos) ? envMsg.find_first_of(".@") : (lenShort + 3); diff --git a/apt-pkg/aptconfiguration.h b/apt-pkg/aptconfiguration.h index c7b8d2d73..fbd9b02e6 100644 --- a/apt-pkg/aptconfiguration.h +++ b/apt-pkg/aptconfiguration.h @@ -16,8 +16,7 @@ #include <limits> /*}}}*/ namespace APT { -class Configuration { /*{{{*/ -public: /*{{{*/ +namespace Configuration { /*{{{*/ /** \brief Returns a vector of usable Compression Types * * Files can be compressed in various ways to decrease the size of the @@ -39,7 +38,7 @@ public: /*{{{*/ * * \return a vector of the compression types in the preferred usage order */ - std::vector<std::string> static const getCompressionTypes(bool const &Cached = true); + std::vector<std::string> const getCompressionTypes(bool const &Cached = true); /** \brief Returns a vector of Language Codes * @@ -64,7 +63,7 @@ public: /*{{{*/ * * \return a vector of (all) Language Codes in the preferred usage order */ - std::vector<std::string> static const getLanguages(bool const &All = false, + std::vector<std::string> const getLanguages(bool const &All = false, bool const &Cached = true, char const ** const Locale = 0); /** \brief Are we interested in the given Language? @@ -73,7 +72,7 @@ public: /*{{{*/ * \param All defines if we check against all codes or only against used codes * \return true if we are interested, false otherwise */ - bool static checkLanguage(std::string Lang, bool const All = false); + bool checkLanguage(std::string Lang, bool const All = false); /** \brief Returns a vector of Architectures we support * @@ -82,14 +81,14 @@ public: /*{{{*/ * * \return a vector of Architectures in preferred order */ - std::vector<std::string> static const getArchitectures(bool const &Cached = true); + std::vector<std::string> const getArchitectures(bool const &Cached = true); /** \brief Are we interested in the given Architecture? * * \param Arch we want to check * \return true if we are interested, false otherwise */ - bool static checkArchitecture(std::string const &Arch); + bool checkArchitecture(std::string const &Arch); /** \brief Representation of supported compressors */ struct Compressor { @@ -113,17 +112,17 @@ public: /*{{{*/ * * \return a vector of Compressors */ - std::vector<Compressor> static const getCompressors(bool const Cached = true); + std::vector<Compressor> const getCompressors(bool const Cached = true); /** \brief Return a vector of extensions supported for data.tar's */ - std::vector<std::string> static const getCompressorExtensions(); + std::vector<std::string> const getCompressorExtensions(); /** \return Return a vector of enabled build profile specifications */ - std::vector<std::string> static const getBuildProfiles(); + std::vector<std::string> const getBuildProfiles(); /** \return Return a comma-separated list of enabled build profile specifications */ - std::string static const getBuildProfilesString(); + std::string const getBuildProfilesString(); /*}}}*/ -}; +} /*}}}*/ } #endif diff --git a/apt-pkg/cachefile.cc b/apt-pkg/cachefile.cc index ea3d45480..214864095 100644 --- a/apt-pkg/cachefile.cc +++ b/apt-pkg/cachefile.cc @@ -35,10 +35,13 @@ #include <apti18n.h> /*}}}*/ // CacheFile::CacheFile - Constructor /*{{{*/ -// --------------------------------------------------------------------- -/* */ -pkgCacheFile::pkgCacheFile() : d(NULL), Map(NULL), Cache(NULL), DCache(NULL), - SrcList(NULL), Policy(NULL) +pkgCacheFile::pkgCacheFile() : d(NULL), ExternOwner(false), Map(NULL), Cache(NULL), + DCache(NULL), SrcList(NULL), Policy(NULL) +{ +} +pkgCacheFile::pkgCacheFile(pkgDepCache * const Owner) : d(NULL), ExternOwner(true), + Map(&Owner->GetCache().GetMap()), Cache(&Owner->GetCache()), + DCache(Owner), SrcList(NULL), Policy(NULL) { } /*}}}*/ @@ -47,12 +50,16 @@ pkgCacheFile::pkgCacheFile() : d(NULL), Map(NULL), Cache(NULL), DCache(NULL), /* */ pkgCacheFile::~pkgCacheFile() { - delete DCache; + if (ExternOwner == false) + { + delete DCache; + delete Cache; + delete Map; + } delete Policy; delete SrcList; - delete Cache; - delete Map; - _system->UnLock(true); + if (ExternOwner == false) + _system->UnLock(true); } /*}}}*/ // CacheFile::BuildCaches - Open and build the cache files /*{{{*/ @@ -65,8 +72,8 @@ bool pkgCacheFile::BuildCaches(OpProgress *Progress, bool WithLock) if (_config->FindB("pkgCacheFile::Generate", true) == false) { - Map = new MMap(*new FileFd(_config->FindFile("Dir::Cache::pkgcache"), - FileFd::ReadOnly),MMap::Public|MMap::ReadOnly); + FileFd file(_config->FindFile("Dir::Cache::pkgcache"), FileFd::ReadOnly); + Map = new MMap(file, MMap::Public|MMap::ReadOnly); Cache = new pkgCache(Map); if (_error->PendingError() == true) return false; @@ -150,8 +157,7 @@ bool pkgCacheFile::BuildDepCache(OpProgress *Progress) if (_error->PendingError() == true) return false; - DCache->Init(Progress); - return true; + return DCache->Init(Progress); } /*}}}*/ // CacheFile::Open - Open the cache files, creating if necessary /*{{{*/ @@ -229,11 +235,16 @@ void pkgCacheFile::RemoveCaches() /* */ void pkgCacheFile::Close() { - delete DCache; + if (ExternOwner == false) + { + delete DCache; + delete Cache; + delete Map; + } + else + ExternOwner = false; delete Policy; - delete Cache; delete SrcList; - delete Map; _system->UnLock(true); Map = NULL; diff --git a/apt-pkg/cachefile.h b/apt-pkg/cachefile.h index 36b20893a..f4cadf5e6 100644 --- a/apt-pkg/cachefile.h +++ b/apt-pkg/cachefile.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: cachefile.h,v 1.5 2002/04/27 04:28:04 jgg Exp $ /* ###################################################################### CacheFile - Simple wrapper class for opening, generating and whatnot @@ -38,10 +37,10 @@ class OpProgress; class pkgCacheFile { /** \brief dpointer placeholder (for later in case we need it) */ - void *d; + void * const d; + bool ExternOwner; protected: - MMap *Map; pkgCache *Cache; pkgDepCache *DCache; @@ -51,18 +50,18 @@ class pkgCacheFile pkgPolicy *Policy; // We look pretty much exactly like a pointer to a dep cache - inline operator pkgCache &() {return *Cache;}; - inline operator pkgCache *() {return Cache;}; - inline operator pkgDepCache &() {return *DCache;}; - inline operator pkgDepCache *() {return DCache;}; - inline operator pkgPolicy &() {return *Policy;}; - inline operator pkgPolicy *() {return Policy;}; - inline operator pkgSourceList &() {return *SrcList;}; - inline operator pkgSourceList *() {return SrcList;}; - inline pkgDepCache *operator ->() {return DCache;}; - inline pkgDepCache &operator *() {return *DCache;}; - inline pkgDepCache::StateCache &operator [](pkgCache::PkgIterator const &I) {return (*DCache)[I];}; - inline unsigned char &operator [](pkgCache::DepIterator const &I) {return (*DCache)[I];}; + inline operator pkgCache &() const {return *Cache;}; + inline operator pkgCache *() const {return Cache;}; + inline operator pkgDepCache &() const {return *DCache;}; + inline operator pkgDepCache *() const {return DCache;}; + inline operator pkgPolicy &() const {return *Policy;}; + inline operator pkgPolicy *() const {return Policy;}; + inline operator pkgSourceList &() const {return *SrcList;}; + inline operator pkgSourceList *() const {return SrcList;}; + inline pkgDepCache *operator ->() const {return DCache;}; + inline pkgDepCache &operator *() const {return *DCache;}; + inline pkgDepCache::StateCache &operator [](pkgCache::PkgIterator const &I) const {return (*DCache)[I];}; + inline unsigned char &operator [](pkgCache::DepIterator const &I) const {return (*DCache)[I];}; bool BuildCaches(OpProgress *Progress = NULL,bool WithLock = true); APT_DEPRECATED bool BuildCaches(OpProgress &Progress,bool const &WithLock = true) { return BuildCaches(&Progress, WithLock); }; @@ -86,6 +85,7 @@ class pkgCacheFile inline bool IsSrcListBuilt() const { return (SrcList != NULL); }; pkgCacheFile(); + explicit pkgCacheFile(pkgDepCache * const Owner); virtual ~pkgCacheFile(); }; diff --git a/apt-pkg/cachefilter.h b/apt-pkg/cachefilter.h index b4697b773..9970b5b22 100644 --- a/apt-pkg/cachefilter.h +++ b/apt-pkg/cachefilter.h @@ -29,34 +29,34 @@ public: class PackageMatcher : public Matcher { public: - virtual bool operator() (pkgCache::PkgIterator const &Pkg) = 0; - virtual bool operator() (pkgCache::VerIterator const &Ver) { return (*this)(Ver.ParentPkg()); } - virtual bool operator() (pkgCache::GrpIterator const &/*Grp*/) { return false; } + virtual bool operator() (pkgCache::PkgIterator const &Pkg) APT_OVERRIDE = 0; + virtual bool operator() (pkgCache::VerIterator const &Ver) APT_OVERRIDE { return (*this)(Ver.ParentPkg()); } + virtual bool operator() (pkgCache::GrpIterator const &/*Grp*/) APT_OVERRIDE { return false; } virtual ~PackageMatcher(); }; // Generica like True, False, NOT, AND, OR /*{{{*/ class TrueMatcher : public Matcher { public: - virtual bool operator() (pkgCache::PkgIterator const &Pkg); - virtual bool operator() (pkgCache::GrpIterator const &Grp); - virtual bool operator() (pkgCache::VerIterator const &Ver); + virtual bool operator() (pkgCache::PkgIterator const &Pkg) APT_OVERRIDE; + virtual bool operator() (pkgCache::GrpIterator const &Grp) APT_OVERRIDE; + virtual bool operator() (pkgCache::VerIterator const &Ver) APT_OVERRIDE; }; class FalseMatcher : public Matcher { public: - virtual bool operator() (pkgCache::PkgIterator const &Pkg); - virtual bool operator() (pkgCache::GrpIterator const &Grp); - virtual bool operator() (pkgCache::VerIterator const &Ver); + virtual bool operator() (pkgCache::PkgIterator const &Pkg) APT_OVERRIDE; + virtual bool operator() (pkgCache::GrpIterator const &Grp) APT_OVERRIDE; + virtual bool operator() (pkgCache::VerIterator const &Ver) APT_OVERRIDE; }; class NOTMatcher : public Matcher { Matcher * const matcher; public: - NOTMatcher(Matcher * const matcher); - virtual bool operator() (pkgCache::PkgIterator const &Pkg); - virtual bool operator() (pkgCache::GrpIterator const &Grp); - virtual bool operator() (pkgCache::VerIterator const &Ver); + explicit NOTMatcher(Matcher * const matcher); + virtual bool operator() (pkgCache::PkgIterator const &Pkg) APT_OVERRIDE; + virtual bool operator() (pkgCache::GrpIterator const &Grp) APT_OVERRIDE; + virtual bool operator() (pkgCache::VerIterator const &Ver) APT_OVERRIDE; virtual ~NOTMatcher(); }; @@ -65,15 +65,15 @@ class ANDMatcher : public Matcher { public: // 5 ought to be enough for everybody… c++11 variadic templates would be nice ANDMatcher(); - ANDMatcher(Matcher * const matcher1); + explicit ANDMatcher(Matcher * const matcher1); ANDMatcher(Matcher * const matcher1, Matcher * const matcher2); ANDMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3); ANDMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3, Matcher * const matcher4); ANDMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3, Matcher * const matcher4, Matcher * const matcher5); ANDMatcher& AND(Matcher * const matcher); - virtual bool operator() (pkgCache::PkgIterator const &Pkg); - virtual bool operator() (pkgCache::GrpIterator const &Grp); - virtual bool operator() (pkgCache::VerIterator const &Ver); + virtual bool operator() (pkgCache::PkgIterator const &Pkg) APT_OVERRIDE; + virtual bool operator() (pkgCache::GrpIterator const &Grp) APT_OVERRIDE; + virtual bool operator() (pkgCache::VerIterator const &Ver) APT_OVERRIDE; virtual ~ANDMatcher(); }; class ORMatcher : public Matcher { @@ -81,33 +81,33 @@ class ORMatcher : public Matcher { public: // 5 ought to be enough for everybody… c++11 variadic templates would be nice ORMatcher(); - ORMatcher(Matcher * const matcher1); + explicit ORMatcher(Matcher * const matcher1); ORMatcher(Matcher * const matcher1, Matcher * const matcher2); ORMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3); ORMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3, Matcher * const matcher4); ORMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3, Matcher * const matcher4, Matcher * const matcher5); ORMatcher& OR(Matcher * const matcher); - virtual bool operator() (pkgCache::PkgIterator const &Pkg); - virtual bool operator() (pkgCache::GrpIterator const &Grp); - virtual bool operator() (pkgCache::VerIterator const &Ver); + virtual bool operator() (pkgCache::PkgIterator const &Pkg) APT_OVERRIDE; + virtual bool operator() (pkgCache::GrpIterator const &Grp) APT_OVERRIDE; + virtual bool operator() (pkgCache::VerIterator const &Ver) APT_OVERRIDE; virtual ~ORMatcher(); }; /*}}}*/ class PackageNameMatchesRegEx : public PackageMatcher { /*{{{*/ regex_t* pattern; public: - PackageNameMatchesRegEx(std::string const &Pattern); - virtual bool operator() (pkgCache::PkgIterator const &Pkg); - virtual bool operator() (pkgCache::GrpIterator const &Grp); + explicit PackageNameMatchesRegEx(std::string const &Pattern); + virtual bool operator() (pkgCache::PkgIterator const &Pkg) APT_OVERRIDE; + virtual bool operator() (pkgCache::GrpIterator const &Grp) APT_OVERRIDE; virtual ~PackageNameMatchesRegEx(); }; /*}}}*/ class PackageNameMatchesFnmatch : public PackageMatcher { /*{{{*/ const std::string Pattern; public: - PackageNameMatchesFnmatch(std::string const &Pattern); - virtual bool operator() (pkgCache::PkgIterator const &Pkg); - virtual bool operator() (pkgCache::GrpIterator const &Grp); + explicit PackageNameMatchesFnmatch(std::string const &Pattern); + virtual bool operator() (pkgCache::PkgIterator const &Pkg) APT_OVERRIDE; + virtual bool operator() (pkgCache::GrpIterator const &Grp) APT_OVERRIDE; virtual ~PackageNameMatchesFnmatch() {}; }; /*}}}*/ @@ -133,15 +133,15 @@ public: */ PackageArchitectureMatchesSpecification(std::string const &pattern, bool const isPattern = true); bool operator() (char const * const &arch); - virtual bool operator() (pkgCache::PkgIterator const &Pkg); + virtual bool operator() (pkgCache::PkgIterator const &Pkg) APT_OVERRIDE; virtual ~PackageArchitectureMatchesSpecification(); }; /*}}}*/ class PackageIsNewInstall : public PackageMatcher { /*{{{*/ pkgCacheFile * const Cache; public: - PackageIsNewInstall(pkgCacheFile * const Cache); - virtual bool operator() (pkgCache::PkgIterator const &Pkg); + explicit PackageIsNewInstall(pkgCacheFile * const Cache); + virtual bool operator() (pkgCache::PkgIterator const &Pkg) APT_OVERRIDE; virtual ~PackageIsNewInstall(); }; /*}}}*/ diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h index fe798799c..48547e564 100644 --- a/apt-pkg/cacheiterators.h +++ b/apt-pkg/cacheiterators.h @@ -43,10 +43,6 @@ need to have for doing some walk-over-the-cache magic */ template<typename Str, typename Itr> class pkgCache::Iterator : public std::iterator<std::forward_iterator_tag, Str> { - protected: - Str *S; - pkgCache *Owner; - /** \brief Returns the Pointer for this struct in the owner * The implementation of this method should be pretty short * as it will only return the Pointer into the mmap stored @@ -55,12 +51,14 @@ template<typename Str, typename Itr> class pkgCache::Iterator : * basic methods from the actual structure. * \return Pointer to the first structure of this type */ - virtual Str* OwnerPointer() const = 0; + Str* OwnerPointer() const { return static_cast<Itr const*>(this)->OwnerPointer(); } + + protected: + Str *S; + pkgCache *Owner; public: // Iteration - virtual void operator ++(int) = 0; - virtual void operator ++() = 0; // Should be {operator ++(0);} inline bool end() const {return Owner == 0 || S == OwnerPointer();} // Comparison @@ -77,7 +75,6 @@ template<typename Str, typename Itr> class pkgCache::Iterator : inline pkgCache *Cache() const {return Owner;} // Mixed stuff - inline void operator =(const Itr &B) {S = B.S; Owner = B.Owner;} inline bool IsGood() const { return S && Owner && ! end();} inline unsigned long Index() const {return S - OwnerPointer();} @@ -100,20 +97,19 @@ template<typename Str, typename Itr> class pkgCache::Iterator : class pkgCache::GrpIterator: public Iterator<Group, GrpIterator> { long HashIndex; - protected: + public: inline Group* OwnerPointer() const { return (Owner != 0) ? Owner->GrpP : 0; } - public: // This constructor is the 'begin' constructor, never use it. - inline GrpIterator(pkgCache &Owner) : Iterator<Group, GrpIterator>(Owner), HashIndex(-1) { + explicit inline GrpIterator(pkgCache &Owner) : Iterator<Group, GrpIterator>(Owner), HashIndex(-1) { S = OwnerPointer(); - operator ++(0); + operator++(); } - virtual void operator ++(int); - virtual void operator ++() {operator ++(0);} + GrpIterator& operator++(); + inline GrpIterator operator++(int) { GrpIterator const tmp(*this); operator++(); return tmp; } inline const char *Name() const {return S->Name == 0?0:Owner->StrP + S->Name;} inline PkgIterator PackageList() const; @@ -141,20 +137,19 @@ class pkgCache::GrpIterator: public Iterator<Group, GrpIterator> { class pkgCache::PkgIterator: public Iterator<Package, PkgIterator> { long HashIndex; - protected: + public: inline Package* OwnerPointer() const { return (Owner != 0) ? Owner->PkgP : 0; } - public: // This constructor is the 'begin' constructor, never use it. - inline PkgIterator(pkgCache &Owner) : Iterator<Package, PkgIterator>(Owner), HashIndex(-1) { + explicit inline PkgIterator(pkgCache &Owner) : Iterator<Package, PkgIterator>(Owner), HashIndex(-1) { S = OwnerPointer(); - operator ++(0); + operator++(); } - virtual void operator ++(int); - virtual void operator ++() {operator ++(0);} + PkgIterator& operator++(); + inline PkgIterator operator++(int) { PkgIterator const tmp(*this); operator++(); return tmp; } enum OkState {NeedsNothing,NeedsUnpack,NeedsConfigure}; @@ -162,11 +157,7 @@ class pkgCache::PkgIterator: public Iterator<Package, PkgIterator> { inline const char *Name() const { return Group().Name(); } // Versions have sections - and packages can have different versions with different sections // so this interface is broken by design. Run as fast as you can to Version.Section(). - APT_DEPRECATED inline const char *Section() const { - APT_IGNORE_DEPRECATED_PUSH - return S->Section == 0?0:Owner->StrP + S->Section; - APT_IGNORE_DEPRECATED_POP - } + APT_DEPRECATED inline const char *Section() const; inline bool Purge() const {return S->CurrentState == pkgCache::State::Purge || (S->CurrentVer == 0 && S->CurrentState == pkgCache::State::NotInstalled);} inline const char *Arch() const {return S->Arch == 0?0:Owner->StrP + S->Arch;} @@ -194,15 +185,14 @@ class pkgCache::PkgIterator: public Iterator<Package, PkgIterator> { /*}}}*/ // Version Iterator /*{{{*/ class pkgCache::VerIterator : public Iterator<Version, VerIterator> { - protected: + public: inline Version* OwnerPointer() const { return (Owner != 0) ? Owner->VerP : 0; } - public: // Iteration - void operator ++(int) {if (S != Owner->VerP) S = Owner->VerP + S->NextVer;} - inline void operator ++() {operator ++(0);} + inline VerIterator& operator++() {if (S != Owner->VerP) S = Owner->VerP + S->NextVer; return *this;} + inline VerIterator operator++(int) { VerIterator const tmp(*this); operator++(); return tmp; } // Comparison int CompareVer(const VerIterator &B) const; @@ -217,14 +207,12 @@ class pkgCache::VerIterator : public Iterator<Version, VerIterator> { // Accessors inline const char *VerStr() const {return S->VerStr == 0?0:Owner->StrP + S->VerStr;} inline const char *Section() const {return S->Section == 0?0:Owner->StrP + S->Section;} -#if APT_PKG_ABI >= 413 /** \brief source package name this version comes from Always contains the name, even if it is the same as the binary name */ inline const char *SourcePkgName() const {return Owner->StrP + S->SourcePkgName;} /** \brief source version this version comes from Always contains the version string, even if it is the same as the binary version */ inline const char *SourceVerStr() const {return Owner->StrP + S->SourceVerStr;} -#endif inline const char *Arch() const { if ((S->MultiArch & pkgCache::Version::All) == pkgCache::Version::All) return "all"; @@ -254,15 +242,14 @@ class pkgCache::VerIterator : public Iterator<Version, VerIterator> { /*}}}*/ // Description Iterator /*{{{*/ class pkgCache::DescIterator : public Iterator<Description, DescIterator> { - protected: + public: inline Description* OwnerPointer() const { return (Owner != 0) ? Owner->DescP : 0; } - public: // Iteration - void operator ++(int) {if (S != Owner->DescP) S = Owner->DescP + S->NextDesc;} - inline void operator ++() {operator ++(0);} + inline DescIterator& operator++() {if (S != Owner->DescP) S = Owner->DescP + S->NextDesc; return *this;} + inline DescIterator operator++(int) { DescIterator const tmp(*this); operator++(); return tmp; } // Comparison int CompareDesc(const DescIterator &B) const; @@ -282,21 +269,20 @@ class pkgCache::DescIterator : public Iterator<Description, DescIterator> { // Dependency iterator /*{{{*/ class pkgCache::DepIterator : public Iterator<Dependency, DepIterator> { enum {DepVer, DepRev} Type; + DependencyData * S2; - protected: + public: inline Dependency* OwnerPointer() const { return (Owner != 0) ? Owner->DepP : 0; } - public: // Iteration - void operator ++(int) {if (S != Owner->DepP) S = Owner->DepP + - (Type == DepVer ? S->NextDepends : S->NextRevDepends);} - inline void operator ++() {operator ++(0);} + DepIterator& operator++(); + inline DepIterator operator++(int) { DepIterator const tmp(*this); operator++(); return tmp; } // Accessors - inline const char *TargetVer() const {return S->Version == 0?0:Owner->StrP + S->Version;} - inline PkgIterator TargetPkg() const {return PkgIterator(*Owner,Owner->PkgP + S->Package);} + inline const char *TargetVer() const {return S2->Version == 0?0:Owner->StrP + S2->Version;} + inline PkgIterator TargetPkg() const {return PkgIterator(*Owner,Owner->PkgP + S2->Package);} inline PkgIterator SmartTargetPkg() const {PkgIterator R(*Owner,0);SmartTargetPkg(R);return R;} inline VerIterator ParentVer() const {return VerIterator(*Owner,Owner->VerP + S->ParentVer);} inline PkgIterator ParentPkg() const {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[S->ParentVer].ParentPkg);} @@ -305,45 +291,79 @@ class pkgCache::DepIterator : public Iterator<Dependency, DepIterator> { bool IsNegative() const APT_PURE; bool IsIgnorable(PrvIterator const &Prv) const APT_PURE; bool IsIgnorable(PkgIterator const &Pkg) const APT_PURE; - bool IsMultiArchImplicit() const APT_PURE; + /* MultiArch can be translated to SingleArch for an resolver and we did so, + by adding dependencies to help the resolver understand the problem, but + sometimes it is needed to identify these to ignore them… */ + inline bool IsMultiArchImplicit() const APT_PURE { + return (S2->CompareOp & pkgCache::Dep::MultiArchImplicit) == pkgCache::Dep::MultiArchImplicit; + } + /* This covers additionally negative dependencies, which aren't arch-specific, + but change architecture nontheless as a Conflicts: foo does applies for all archs */ + bool IsImplicit() const APT_PURE; + bool IsSatisfied(VerIterator const &Ver) const APT_PURE; bool IsSatisfied(PrvIterator const &Prv) const APT_PURE; void GlobOr(DepIterator &Start,DepIterator &End); Version **AllTargets() const; bool SmartTargetPkg(PkgIterator &Result) const; - inline const char *CompType() const {return Owner->CompType(S->CompareOp);} - inline const char *DepType() const {return Owner->DepType(S->Type);} + inline const char *CompType() const {return Owner->CompType(S2->CompareOp);} + inline const char *DepType() const {return Owner->DepType(S2->Type);} + + // overrides because we are special + struct DependencyProxy + { + map_stringitem_t &Version; + map_pointer_t &Package; + map_id_t &ID; + unsigned char &Type; + unsigned char &CompareOp; + map_pointer_t &ParentVer; + map_pointer_t &DependencyData; + map_pointer_t &NextRevDepends; + map_pointer_t &NextDepends; + map_pointer_t &NextData; + DependencyProxy const * operator->() const { return this; } + DependencyProxy * operator->() { return this; } + }; + inline DependencyProxy operator->() const {return (DependencyProxy) { S2->Version, S2->Package, S->ID, S2->Type, S2->CompareOp, S->ParentVer, S->DependencyData, S->NextRevDepends, S->NextDepends, S2->NextData };} + inline DependencyProxy operator->() {return (DependencyProxy) { S2->Version, S2->Package, S->ID, S2->Type, S2->CompareOp, S->ParentVer, S->DependencyData, S->NextRevDepends, S->NextDepends, S2->NextData };} + void ReMap(void const * const oldMap, void const * const newMap) + { + Iterator<Dependency, DepIterator>::ReMap(oldMap, newMap); + if (Owner == 0 || S == 0 || S2 == 0) + return; + S2 += (DependencyData const * const)(newMap) - (DependencyData const * const)(oldMap); + } //Nice printable representation friend std::ostream& operator <<(std::ostream& out, DepIterator D); inline DepIterator(pkgCache &Owner, Dependency *Trg, Version* = 0) : - Iterator<Dependency, DepIterator>(Owner, Trg), Type(DepVer) { + Iterator<Dependency, DepIterator>(Owner, Trg), Type(DepVer), S2(Trg == 0 ? Owner.DepDataP : (Owner.DepDataP + Trg->DependencyData)) { if (S == 0) S = Owner.DepP; } inline DepIterator(pkgCache &Owner, Dependency *Trg, Package*) : - Iterator<Dependency, DepIterator>(Owner, Trg), Type(DepRev) { + Iterator<Dependency, DepIterator>(Owner, Trg), Type(DepRev), S2(Trg == 0 ? Owner.DepDataP : (Owner.DepDataP + Trg->DependencyData)) { if (S == 0) S = Owner.DepP; } - inline DepIterator() : Iterator<Dependency, DepIterator>(), Type(DepVer) {} + inline DepIterator() : Iterator<Dependency, DepIterator>(), Type(DepVer), S2(0) {} }; /*}}}*/ // Provides iterator /*{{{*/ class pkgCache::PrvIterator : public Iterator<Provides, PrvIterator> { enum {PrvVer, PrvPkg} Type; - protected: + public: inline Provides* OwnerPointer() const { return (Owner != 0) ? Owner->ProvideP : 0; } - public: // Iteration - void operator ++(int) {if (S != Owner->ProvideP) S = Owner->ProvideP + - (Type == PrvVer?S->NextPkgProv:S->NextProvides);} - inline void operator ++() {operator ++(0);} + inline PrvIterator& operator ++() {if (S != Owner->ProvideP) S = Owner->ProvideP + + (Type == PrvVer?S->NextPkgProv:S->NextProvides); return *this;} + inline PrvIterator operator++(int) { PrvIterator const tmp(*this); operator++(); return tmp; } // Accessors inline const char *Name() const {return ParentPkg().Name();} @@ -352,7 +372,12 @@ class pkgCache::PrvIterator : public Iterator<Provides, PrvIterator> { inline VerIterator OwnerVer() const {return VerIterator(*Owner,Owner->VerP + S->Version);} inline PkgIterator OwnerPkg() const {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[S->Version].ParentPkg);} - bool IsMultiArchImplicit() const APT_PURE; + /* MultiArch can be translated to SingleArch for an resolver and we did so, + by adding provides to help the resolver understand the problem, but + sometimes it is needed to identify these to ignore them… */ + bool IsMultiArchImplicit() const APT_PURE + { return (S->Flags & pkgCache::Flag::MultiArchImplicit) == pkgCache::Flag::MultiArchImplicit; } + inline PrvIterator() : Iterator<Provides, PrvIterator>(), Type(PrvVer) {} inline PrvIterator(pkgCache &Owner, Provides *Trg, Version*) : @@ -367,27 +392,59 @@ class pkgCache::PrvIterator : public Iterator<Provides, PrvIterator> { } }; /*}}}*/ -// Package file /*{{{*/ -class pkgCache::PkgFileIterator : public Iterator<PackageFile, PkgFileIterator> { - protected: - inline PackageFile* OwnerPointer() const { - return (Owner != 0) ? Owner->PkgFileP : 0; +// Release file /*{{{*/ +class pkgCache::RlsFileIterator : public Iterator<ReleaseFile, RlsFileIterator> { + public: + inline ReleaseFile* OwnerPointer() const { + return (Owner != 0) ? Owner->RlsFileP : 0; } - public: // Iteration - void operator ++(int) {if (S != Owner->PkgFileP) S = Owner->PkgFileP + S->NextFile;} - inline void operator ++() {operator ++(0);} + inline RlsFileIterator& operator++() {if (S != Owner->RlsFileP) S = Owner->RlsFileP + S->NextFile;return *this;} + inline RlsFileIterator operator++(int) { RlsFileIterator const tmp(*this); operator++(); return tmp; } // Accessors inline const char *FileName() const {return S->FileName == 0?0:Owner->StrP + S->FileName;} inline const char *Archive() const {return S->Archive == 0?0:Owner->StrP + S->Archive;} - inline const char *Component() const {return S->Component == 0?0:Owner->StrP + S->Component;} inline const char *Version() const {return S->Version == 0?0:Owner->StrP + S->Version;} inline const char *Origin() const {return S->Origin == 0?0:Owner->StrP + S->Origin;} inline const char *Codename() const {return S->Codename ==0?0:Owner->StrP + S->Codename;} inline const char *Label() const {return S->Label == 0?0:Owner->StrP + S->Label;} inline const char *Site() const {return S->Site == 0?0:Owner->StrP + S->Site;} + inline bool Flagged(pkgCache::Flag::ReleaseFileFlags const flag) const {return (S->Flags & flag) == flag; } + + bool IsOk(); + std::string RelStr(); + + // Constructors + inline RlsFileIterator() : Iterator<ReleaseFile, RlsFileIterator>() {} + explicit inline RlsFileIterator(pkgCache &Owner) : Iterator<ReleaseFile, RlsFileIterator>(Owner, Owner.RlsFileP) {} + inline RlsFileIterator(pkgCache &Owner,ReleaseFile *Trg) : Iterator<ReleaseFile, RlsFileIterator>(Owner, Trg) {} +}; + /*}}}*/ +// Package file /*{{{*/ +class pkgCache::PkgFileIterator : public Iterator<PackageFile, PkgFileIterator> { + public: + inline PackageFile* OwnerPointer() const { + return (Owner != 0) ? Owner->PkgFileP : 0; + } + + // Iteration + inline PkgFileIterator& operator++() {if (S != Owner->PkgFileP) S = Owner->PkgFileP + S->NextFile; return *this;} + inline PkgFileIterator operator++(int) { PkgFileIterator const tmp(*this); operator++(); return tmp; } + + // Accessors + inline const char *FileName() const {return S->FileName == 0?0:Owner->StrP + S->FileName;} + inline pkgCache::RlsFileIterator ReleaseFile() const {return RlsFileIterator(*Owner, Owner->RlsFileP + S->Release);} + inline const char *Archive() const {return S->Release == 0 ? Component() : ReleaseFile().Archive();} + inline const char *Version() const {return S->Release == 0 ? NULL : ReleaseFile().Version();} + inline const char *Origin() const {return S->Release == 0 ? NULL : ReleaseFile().Origin();} + inline const char *Codename() const {return S->Release == 0 ? NULL : ReleaseFile().Codename();} + inline const char *Label() const {return S->Release == 0 ? NULL : ReleaseFile().Label();} + inline const char *Site() const {return S->Release == 0 ? NULL : ReleaseFile().Site();} + inline bool Flagged(pkgCache::Flag::ReleaseFileFlags const flag) const {return S->Release== 0 ? false : ReleaseFile().Flagged(flag);} + inline bool Flagged(pkgCache::Flag::PkgFFlags const flag) const {return (S->Flags & flag) == flag;} + inline const char *Component() const {return S->Component == 0?0:Owner->StrP + S->Component;} inline const char *Architecture() const {return S->Architecture == 0?0:Owner->StrP + S->Architecture;} inline const char *IndexType() const {return S->IndexType == 0?0:Owner->StrP + S->IndexType;} @@ -396,21 +453,20 @@ class pkgCache::PkgFileIterator : public Iterator<PackageFile, PkgFileIterator> // Constructors inline PkgFileIterator() : Iterator<PackageFile, PkgFileIterator>() {} - inline PkgFileIterator(pkgCache &Owner) : Iterator<PackageFile, PkgFileIterator>(Owner, Owner.PkgFileP) {} + explicit inline PkgFileIterator(pkgCache &Owner) : Iterator<PackageFile, PkgFileIterator>(Owner, Owner.PkgFileP) {} inline PkgFileIterator(pkgCache &Owner,PackageFile *Trg) : Iterator<PackageFile, PkgFileIterator>(Owner, Trg) {} }; /*}}}*/ // Version File /*{{{*/ class pkgCache::VerFileIterator : public pkgCache::Iterator<VerFile, VerFileIterator> { - protected: + public: inline VerFile* OwnerPointer() const { return (Owner != 0) ? Owner->VerFileP : 0; } - public: // Iteration - void operator ++(int) {if (S != Owner->VerFileP) S = Owner->VerFileP + S->NextFile;} - inline void operator ++() {operator ++(0);} + inline VerFileIterator& operator++() {if (S != Owner->VerFileP) S = Owner->VerFileP + S->NextFile; return *this;} + inline VerFileIterator operator++(int) { VerFileIterator const tmp(*this); operator++(); return tmp; } // Accessors inline PkgFileIterator File() const {return PkgFileIterator(*Owner,S->File + Owner->PkgFileP);} @@ -421,15 +477,14 @@ class pkgCache::VerFileIterator : public pkgCache::Iterator<VerFile, VerFileIter /*}}}*/ // Description File /*{{{*/ class pkgCache::DescFileIterator : public Iterator<DescFile, DescFileIterator> { - protected: + public: inline DescFile* OwnerPointer() const { return (Owner != 0) ? Owner->DescFileP : 0; } - public: // Iteration - void operator ++(int) {if (S != Owner->DescFileP) S = Owner->DescFileP + S->NextFile;} - inline void operator ++() {operator ++(0);} + inline DescFileIterator& operator++() {if (S != Owner->DescFileP) S = Owner->DescFileP + S->NextFile; return *this;} + inline DescFileIterator operator++(int) { DescFileIterator const tmp(*this); operator++(); return tmp; } // Accessors inline PkgFileIterator File() const {return PkgFileIterator(*Owner,S->File + Owner->PkgFileP);} @@ -459,5 +514,7 @@ inline pkgCache::VerFileIterator pkgCache::VerIterator::FileList() const {return VerFileIterator(*Owner,Owner->VerFileP + S->FileList);} inline pkgCache::DescFileIterator pkgCache::DescIterator::FileList() const {return DescFileIterator(*Owner,Owner->DescFileP + S->FileList);} +APT_DEPRECATED inline const char * pkgCache::PkgIterator::Section() const + {return S->VersionList == 0 ? 0 : VersionList().Section();} /*}}}*/ #endif diff --git a/apt-pkg/cacheset.cc b/apt-pkg/cacheset.cc index 0ad99713a..af607a197 100644 --- a/apt-pkg/cacheset.cc +++ b/apt-pkg/cacheset.cc @@ -37,7 +37,6 @@ #include <apti18n.h> /*}}}*/ namespace APT { - // PackageFrom - selecting the appropriate method for package selection /*{{{*/ bool CacheSetHelper::PackageFrom(enum PkgSelector const select, PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string const &pattern) { @@ -583,6 +582,116 @@ bool VersionContainerInterface::FromPackage(VersionContainerInterface * const vc return found; } /*}}}*/ +// FromDependency - versions satisfying a given dependency /*{{{*/ +bool VersionContainerInterface::FromDependency(VersionContainerInterface * const vci, + pkgCacheFile &Cache, + pkgCache::DepIterator const &D, + CacheSetHelper::VerSelector const selector, + CacheSetHelper &helper) +{ + bool found = false; + switch(selector) { + case CacheSetHelper::ALL: + { + pkgCache::PkgIterator const T = D.TargetPkg(); + for (pkgCache::VerIterator Ver = T.VersionList(); Ver.end() == false; ++Ver) + { + if (D.IsSatisfied(Ver) == true) + { + vci->insert(Ver); + found = true; + } + for (pkgCache::PrvIterator Prv = T.ProvidesList(); Prv.end() != true; ++Prv) + { + pkgCache::VerIterator const V = Prv.OwnerVer(); + if (unlikely(V.end() == true) || D.IsSatisfied(Prv) == false) + continue; + vci->insert(V); + found = true; + } + } + return found; + } + case CacheSetHelper::CANDANDINST: + { + found = FromDependency(vci, Cache, D, CacheSetHelper::CANDIDATE, helper); + found &= FromDependency(vci, Cache, D, CacheSetHelper::INSTALLED, helper); + return found; + } + case CacheSetHelper::CANDIDATE: + { + pkgCache::PkgIterator const T = D.TargetPkg(); + pkgCache::VerIterator const Cand = Cache[T].CandidateVerIter(Cache); + if (Cand.end() == false && D.IsSatisfied(Cand) == true) + { + vci->insert(Cand); + found = true; + } + for (pkgCache::PrvIterator Prv = T.ProvidesList(); Prv.end() != true; ++Prv) + { + pkgCache::VerIterator const V = Prv.OwnerVer(); + pkgCache::VerIterator const Cand = Cache[Prv.OwnerPkg()].CandidateVerIter(Cache); + if (Cand.end() == true || V != Cand || D.IsSatisfied(Prv) == false) + continue; + vci->insert(Cand); + found = true; + } + return found; + } + case CacheSetHelper::INSTALLED: + { + pkgCache::PkgIterator const T = D.TargetPkg(); + pkgCache::VerIterator const Cand = T.CurrentVer(); + if (Cand.end() == false && D.IsSatisfied(Cand) == true) + { + vci->insert(Cand); + found = true; + } + for (pkgCache::PrvIterator Prv = T.ProvidesList(); Prv.end() != true; ++Prv) + { + pkgCache::VerIterator const V = Prv.OwnerVer(); + pkgCache::VerIterator const Cand = Prv.OwnerPkg().CurrentVer(); + if (Cand.end() == true || V != Cand || D.IsSatisfied(Prv) == false) + continue; + vci->insert(Cand); + found = true; + } + return found; + } + case CacheSetHelper::CANDINST: + return FromDependency(vci, Cache, D, CacheSetHelper::CANDIDATE, helper) || + FromDependency(vci, Cache, D, CacheSetHelper::INSTALLED, helper); + case CacheSetHelper::INSTCAND: + return FromDependency(vci, Cache, D, CacheSetHelper::INSTALLED, helper) || + FromDependency(vci, Cache, D, CacheSetHelper::CANDIDATE, helper); + case CacheSetHelper::NEWEST: + { + pkgCache::PkgIterator const T = D.TargetPkg(); + pkgCache::VerIterator const Cand = T.VersionList(); + if (Cand.end() == false && D.IsSatisfied(Cand) == true) + { + vci->insert(Cand); + found = true; + } + for (pkgCache::PrvIterator Prv = T.ProvidesList(); Prv.end() != true; ++Prv) + { + pkgCache::VerIterator const V = Prv.OwnerVer(); + pkgCache::VerIterator const Cand = Prv.OwnerPkg().VersionList(); + if (Cand.end() == true || V != Cand || D.IsSatisfied(Prv) == false) + continue; + vci->insert(Cand); + found = true; + } + return found; + } + case CacheSetHelper::RELEASE: + case CacheSetHelper::VERSIONNUMBER: + // both make no sense here, so always false + return false; + } + return found; +} + /*}}}*/ // getCandidateVer - Returns the candidate version of the given package /*{{{*/ pkgCache::VerIterator VersionContainerInterface::getCandidateVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg, CacheSetHelper &helper) { @@ -812,4 +921,28 @@ APT_CONST void CacheSetHelper::showSelectedVersion(pkgCache::PkgIterator const & bool const /*verIsRel*/) { } /*}}}*/ + +CacheSetHelper::CacheSetHelper(bool const ShowError, GlobalError::MsgType ErrorType) : + ShowError(ShowError), ErrorType(ErrorType), d(NULL) {} +CacheSetHelper::~CacheSetHelper() {} + +PackageContainerInterface::PackageContainerInterface() : ConstructedBy(CacheSetHelper::UNKNOWN), d(NULL) {} +PackageContainerInterface::PackageContainerInterface(CacheSetHelper::PkgSelector const by) : ConstructedBy(by), d(NULL) {} +PackageContainerInterface& PackageContainerInterface::operator=(PackageContainerInterface const &other) { + if (this != &other) + this->ConstructedBy = other.ConstructedBy; + return *this; +} +PackageContainerInterface::~PackageContainerInterface() {} + +PackageUniverse::PackageUniverse(pkgCache * const Owner) : _cont(Owner), d(NULL) {} +PackageUniverse::PackageUniverse(pkgCacheFile * const Owner) : _cont(Owner->GetPkgCache()), d(NULL) {} +PackageUniverse::~PackageUniverse() {} + +VersionContainerInterface::VersionContainerInterface() : d(NULL) {} +VersionContainerInterface& VersionContainerInterface::operator=(VersionContainerInterface const &) { + return *this; +} + +VersionContainerInterface::~VersionContainerInterface() {} } diff --git a/apt-pkg/cacheset.h b/apt-pkg/cacheset.h index 97aee8c2d..7c03ad97a 100644 --- a/apt-pkg/cacheset.h +++ b/apt-pkg/cacheset.h @@ -12,7 +12,12 @@ #include <fstream> #include <map> #include <set> +#if __cplusplus >= 201103L +#include <unordered_set> +#include <forward_list> +#endif #include <list> +#include <deque> #include <vector> #include <string> #include <iterator> @@ -50,9 +55,8 @@ class CacheSetHelper { /*{{{*/ */ public: /*{{{*/ CacheSetHelper(bool const ShowError = true, - GlobalError::MsgType ErrorType = GlobalError::ERROR) : - ShowError(ShowError), ErrorType(ErrorType) {} - virtual ~CacheSetHelper() {} + GlobalError::MsgType ErrorType = GlobalError::ERROR); + virtual ~CacheSetHelper(); enum PkgSelector { UNKNOWN, REGEX, TASK, FNMATCH, PACKAGENAME, STRING }; @@ -203,8 +207,92 @@ protected: bool PackageFromFnmatch(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern); bool PackageFromPackageName(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern); bool PackageFromString(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string const &pattern); +private: + void * const d; }; /*}}}*/ +// Iterator templates for our Containers /*{{{*/ +template<typename Interface, typename Master, typename iterator_type, typename container_iterator, typename container_value> class Container_iterator_base : + public std::iterator<typename std::iterator_traits<container_iterator>::iterator_category, container_iterator>, + public Interface::template iterator_base<iterator_type> +{ +protected: + container_iterator _iter; +public: + explicit Container_iterator_base(container_iterator i) : _iter(i) {} + inline container_value operator*(void) const { return static_cast<iterator_type const*>(this)->getType(); }; + operator container_iterator(void) const { return _iter; } + inline iterator_type& operator++() { ++_iter; return static_cast<iterator_type&>(*this); } + inline iterator_type operator++(int) { iterator_type tmp(*this); operator++(); return tmp; } + inline iterator_type operator+(typename container_iterator::difference_type const &n) { return iterator_type(_iter + n); } + inline iterator_type operator+=(typename container_iterator::difference_type const &n) { _iter += n; return static_cast<iterator_type&>(*this); } + inline iterator_type& operator--() { --_iter;; return static_cast<iterator_type&>(*this); } + inline iterator_type operator--(int) { iterator_type tmp(*this); operator--(); return tmp; } + inline iterator_type operator-(typename container_iterator::difference_type const &n) { return iterator_type(_iter - n); } + inline iterator_type operator-=(typename container_iterator::difference_type const &n) { _iter -= n; return static_cast<iterator_type&>(*this); } + inline bool operator!=(iterator_type const &i) const { return _iter != i._iter; } + inline bool operator==(iterator_type const &i) const { return _iter == i._iter; } + inline bool operator<(iterator_type const &i) const { return _iter < i._iter; } + inline bool operator>(iterator_type const &i) const { return _iter > i._iter; } + inline bool operator<=(iterator_type const &i) const { return _iter <= i._iter; } + inline bool operator>=(iterator_type const &i) const { return _iter >= i._iter; } + inline typename container_iterator::reference operator[](typename container_iterator::difference_type const &n) const { return _iter[n]; } + + friend std::ostream& operator<<(std::ostream& out, iterator_type i) { return operator<<(out, *i); } + friend Master; +}; +template<class Interface, class Container, class Master> class Container_const_iterator : + public Container_iterator_base<Interface, Master, Container_const_iterator<Interface, Container, Master>, typename Container::const_iterator, typename Container::value_type> +{ + typedef Container_const_iterator<Interface, Container, Master> iterator_type; + typedef typename Container::const_iterator container_iterator; +public: + explicit Container_const_iterator(container_iterator i) : + Container_iterator_base<Interface, Master, iterator_type, container_iterator, typename Container::value_type>(i) {} + + inline typename Container::value_type getType(void) const { return *this->_iter; } +}; +template<class Interface, class Container, class Master> class Container_iterator : + public Container_iterator_base<Interface, Master, Container_iterator<Interface, Container, Master>, typename Container::iterator, typename Container::value_type> +{ + typedef Container_iterator<Interface, Container, Master> iterator_type; + typedef typename Container::iterator container_iterator; +public: + explicit Container_iterator(container_iterator i) : + Container_iterator_base<Interface, Master, iterator_type, container_iterator, typename Container::value_type>(i) {} + + operator typename Master::const_iterator() { return typename Master::const_iterator(this->_iter); } + inline iterator_type& operator=(iterator_type const &i) { this->_iter = i._iter; return static_cast<iterator_type&>(*this); } + inline iterator_type& operator=(container_iterator const &i) { this->_iter = i; return static_cast<iterator_type&>(*this); } + + inline typename Container::value_type getType(void) const { return *this->_iter; } +}; +template<class Interface, class Container, class Master> class Container_const_reverse_iterator : + public Container_iterator_base<Interface, Master, Container_const_reverse_iterator<Interface, Container, Master>, typename Container::const_reverse_iterator, typename Container::value_type> +{ + typedef Container_const_reverse_iterator<Interface, Container, Master> iterator_type; + typedef typename Container::const_reverse_iterator container_iterator; +public: + explicit Container_const_reverse_iterator(container_iterator i) : + Container_iterator_base<Interface, Master, iterator_type, container_iterator, typename Container::value_type>(i) {} + + inline typename Container::value_type getType(void) const { return *this->_iter; } +}; +template<class Interface, class Container, class Master> class Container_reverse_iterator : + public Container_iterator_base<Interface, Master, Container_reverse_iterator<Interface, Container, Master>, typename Container::reverse_iterator, typename Container::value_type> +{ + typedef Container_reverse_iterator<Interface, Container, Master> iterator_type; + typedef typename Container::reverse_iterator container_iterator; +public: + explicit Container_reverse_iterator(container_iterator i) : + Container_iterator_base<Interface, Master, iterator_type, container_iterator, typename Container::value_type>(i) {} + + operator typename Master::const_iterator() { return typename Master::const_iterator(this->_iter); } + inline iterator_type& operator=(iterator_type const &i) { this->_iter = i._iter; return static_cast<iterator_type&>(*this); } + inline iterator_type& operator=(container_iterator const &i) { this->_iter = i; return static_cast<iterator_type&>(*this); } + inline typename Container::value_type getType(void) const { return *this->_iter; } +}; + /*}}}*/ class PackageContainerInterface { /*{{{*/ /** \class PackageContainerInterface @@ -216,41 +304,42 @@ class PackageContainerInterface { /*{{{*/ * This class mostly protects use from the need to write all implementation * of the methods working on containers in the template */ public: - class const_iterator { /*{{{*/ + template<class Itr> class iterator_base { /*{{{*/ + pkgCache::PkgIterator getType() const { return static_cast<Itr const*>(this)->getType(); }; public: - virtual pkgCache::PkgIterator getPkg() const = 0; - operator pkgCache::PkgIterator(void) const { return getPkg(); } + operator pkgCache::PkgIterator(void) const { return getType(); } - inline const char *Name() const {return getPkg().Name(); } - inline std::string FullName(bool const Pretty) const { return getPkg().FullName(Pretty); } - inline std::string FullName() const { return getPkg().FullName(); } + inline const char *Name() const {return getType().Name(); } + inline std::string FullName(bool const Pretty) const { return getType().FullName(Pretty); } + inline std::string FullName() const { return getType().FullName(); } APT_DEPRECATED inline const char *Section() const { APT_IGNORE_DEPRECATED_PUSH - return getPkg().Section(); + return getType().Section(); APT_IGNORE_DEPRECATED_POP } - inline bool Purge() const {return getPkg().Purge(); } - inline const char *Arch() const {return getPkg().Arch(); } - inline pkgCache::GrpIterator Group() const { return getPkg().Group(); } - inline pkgCache::VerIterator VersionList() const { return getPkg().VersionList(); } - inline pkgCache::VerIterator CurrentVer() const { return getPkg().CurrentVer(); } - inline pkgCache::DepIterator RevDependsList() const { return getPkg().RevDependsList(); } - inline pkgCache::PrvIterator ProvidesList() const { return getPkg().ProvidesList(); } - inline pkgCache::PkgIterator::OkState State() const { return getPkg().State(); } - inline const char *CandVersion() const { return getPkg().CandVersion(); } - inline const char *CurVersion() const { return getPkg().CurVersion(); } - inline pkgCache *Cache() const { return getPkg().Cache(); } - inline unsigned long Index() const {return getPkg().Index();} + inline bool Purge() const {return getType().Purge(); } + inline const char *Arch() const {return getType().Arch(); } + inline pkgCache::GrpIterator Group() const { return getType().Group(); } + inline pkgCache::VerIterator VersionList() const { return getType().VersionList(); } + inline pkgCache::VerIterator CurrentVer() const { return getType().CurrentVer(); } + inline pkgCache::DepIterator RevDependsList() const { return getType().RevDependsList(); } + inline pkgCache::PrvIterator ProvidesList() const { return getType().ProvidesList(); } + inline pkgCache::PkgIterator::OkState State() const { return getType().State(); } + inline const char *CandVersion() const { return getType().CandVersion(); } + inline const char *CurVersion() const { return getType().CurVersion(); } + inline pkgCache *Cache() const { return getType().Cache(); } + inline unsigned long Index() const {return getType().Index();} // we have only valid iterators here inline bool end() const { return false; } - inline pkgCache::Package const * operator->() const {return &*getPkg();} + inline pkgCache::Package const * operator->() const {return &*getType();} }; /*}}}*/ virtual bool insert(pkgCache::PkgIterator const &P) = 0; virtual bool empty() const = 0; virtual void clear() = 0; + virtual size_t size() const = 0; // FIXME: This is a bloody hack removed soon. Use CacheSetHelper::PkgSelector ! enum APT_DEPRECATED Constructor { UNKNOWN = CacheSetHelper::UNKNOWN, @@ -263,8 +352,10 @@ APT_IGNORE_DEPRECATED_POP void setConstructor(CacheSetHelper::PkgSelector const by) { ConstructedBy = by; } CacheSetHelper::PkgSelector getConstructor() const { return ConstructedBy; } - PackageContainerInterface() : ConstructedBy(CacheSetHelper::UNKNOWN) {} - PackageContainerInterface(CacheSetHelper::PkgSelector const by) : ConstructedBy(by) {} + PackageContainerInterface(); + explicit PackageContainerInterface(CacheSetHelper::PkgSelector const by); + PackageContainerInterface& operator=(PackageContainerInterface const &other); + virtual ~PackageContainerInterface(); APT_DEPRECATED static bool FromTask(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper) { return helper.PackageFrom(CacheSetHelper::TASK, pci, Cache, pattern); } @@ -292,6 +383,7 @@ APT_IGNORE_DEPRECATED_POP private: CacheSetHelper::PkgSelector ConstructedBy; + void * const d; }; /*}}}*/ template<class Container> class PackageContainer : public PackageContainerInterface {/*{{{*/ @@ -303,60 +395,43 @@ template<class Container> class PackageContainer : public PackageContainerInterf Container _cont; public: /*{{{*/ /** \brief smell like a pkgCache::PkgIterator */ - class const_iterator : public PackageContainerInterface::const_iterator,/*{{{*/ - public std::iterator<std::forward_iterator_tag, typename Container::const_iterator> { - typename Container::const_iterator _iter; - public: - const_iterator(typename Container::const_iterator i) : _iter(i) {} - pkgCache::PkgIterator getPkg(void) const { return *_iter; } - inline pkgCache::PkgIterator operator*(void) const { return *_iter; } - operator typename Container::const_iterator(void) const { return _iter; } - inline const_iterator& operator++() { ++_iter; return *this; } - inline const_iterator operator++(int) { const_iterator tmp(*this); operator++(); return tmp; } - inline bool operator!=(const_iterator const &i) const { return _iter != i._iter; } - inline bool operator==(const_iterator const &i) const { return _iter == i._iter; } - friend std::ostream& operator<<(std::ostream& out, const_iterator i) { return operator<<(out, *i); } - }; - class iterator : public PackageContainerInterface::const_iterator, - public std::iterator<std::forward_iterator_tag, typename Container::iterator> { - typename Container::iterator _iter; - public: - iterator(typename Container::iterator i) : _iter(i) {} - pkgCache::PkgIterator getPkg(void) const { return *_iter; } - inline pkgCache::PkgIterator operator*(void) const { return *_iter; } - operator typename Container::iterator(void) const { return _iter; } - operator typename PackageContainer<Container>::const_iterator() { return typename PackageContainer<Container>::const_iterator(_iter); } - inline iterator& operator++() { ++_iter; return *this; } - inline iterator operator++(int) { iterator tmp(*this); operator++(); return tmp; } - inline bool operator!=(iterator const &i) const { return _iter != i._iter; } - inline bool operator==(iterator const &i) const { return _iter == i._iter; } - inline iterator& operator=(iterator const &i) { _iter = i._iter; return *this; } - inline iterator& operator=(typename Container::iterator const &i) { _iter = i; return *this; } - friend std::ostream& operator<<(std::ostream& out, iterator i) { return operator<<(out, *i); } - }; - /*}}}*/ + typedef Container_const_iterator<PackageContainerInterface, Container, PackageContainer> const_iterator; + typedef Container_iterator<PackageContainerInterface, Container, PackageContainer> iterator; + typedef Container_const_reverse_iterator<PackageContainerInterface, Container, PackageContainer> const_reverse_iterator; + typedef Container_reverse_iterator<PackageContainerInterface, Container, PackageContainer> reverse_iterator; - bool insert(pkgCache::PkgIterator const &P) { if (P.end() == true) return false; _cont.insert(P); return true; } + bool insert(pkgCache::PkgIterator const &P) APT_OVERRIDE { if (P.end() == true) return false; _cont.insert(P); return true; } template<class Cont> void insert(PackageContainer<Cont> const &pkgcont) { _cont.insert((typename Cont::const_iterator)pkgcont.begin(), (typename Cont::const_iterator)pkgcont.end()); } void insert(const_iterator begin, const_iterator end) { _cont.insert(begin, end); } - bool empty() const { return _cont.empty(); } - void clear() { return _cont.clear(); } - //FIXME: on ABI break, replace the first with the second without bool - void erase(iterator position) { _cont.erase((typename Container::iterator)position); } - iterator& erase(iterator &position, bool) { return position = _cont.erase((typename Container::iterator)position); } - size_t erase(const pkgCache::PkgIterator x) { return _cont.erase(x); } - void erase(iterator first, iterator last) { _cont.erase(first, last); } - size_t size() const { return _cont.size(); } - + bool empty() const APT_OVERRIDE { return _cont.empty(); } + void clear() APT_OVERRIDE { return _cont.clear(); } + size_t size() const APT_OVERRIDE { return _cont.size(); } +#if __GNUC__ >= 5 || (__GNUC_MINOR__ >= 9 && __GNUC__ >= 4) + iterator erase( const_iterator pos ) { return iterator(_cont.erase(pos._iter)); } + iterator erase( const_iterator first, const_iterator last ) { return iterator(_cont.erase(first._iter, last._iter)); } +#else + iterator erase( iterator pos ) { return iterator(_cont.erase(pos._iter)); } + iterator erase( iterator first, iterator last ) { return iterator(_cont.erase(first._iter, last._iter)); } +#endif const_iterator begin() const { return const_iterator(_cont.begin()); } const_iterator end() const { return const_iterator(_cont.end()); } + const_reverse_iterator rbegin() const { return const_reverse_iterator(_cont.rbegin()); } + const_reverse_iterator rend() const { return const_reverse_iterator(_cont.rend()); } +#if __cplusplus >= 201103L + const_iterator cbegin() const { return const_iterator(_cont.cbegin()); } + const_iterator cend() const { return const_iterator(_cont.cend()); } + const_reverse_iterator crbegin() const { return const_reverse_iterator(_cont.crbegin()); } + const_reverse_iterator crend() const { return const_reverse_iterator(_cont.crend()); } +#endif iterator begin() { return iterator(_cont.begin()); } iterator end() { return iterator(_cont.end()); } + reverse_iterator rbegin() { return reverse_iterator(_cont.rbegin()); } + reverse_iterator rend() { return reverse_iterator(_cont.rend()); } const_iterator find(pkgCache::PkgIterator const &P) const { return const_iterator(_cont.find(P)); } - PackageContainer() : PackageContainerInterface() {} - PackageContainer(CacheSetHelper::PkgSelector const &by) : PackageContainerInterface(by) {} + PackageContainer() : PackageContainerInterface(CacheSetHelper::UNKNOWN) {} + explicit PackageContainer(CacheSetHelper::PkgSelector const &by) : PackageContainerInterface(by) {} APT_IGNORE_DEPRECATED_PUSH APT_DEPRECATED PackageContainer(Constructor const &by) : PackageContainerInterface((CacheSetHelper::PkgSelector)by) {} APT_IGNORE_DEPRECATED_POP @@ -504,16 +579,26 @@ APT_IGNORE_DEPRECATED_POP } /*}}}*/ }; /*}}}*/ -// specialisations for push_back containers: std::list & std::vector /*{{{*/ +// various specialisations for PackageContainer /*{{{*/ template<> template<class Cont> void PackageContainer<std::list<pkgCache::PkgIterator> >::insert(PackageContainer<Cont> const &pkgcont) { for (typename PackageContainer<Cont>::const_iterator p = pkgcont.begin(); p != pkgcont.end(); ++p) _cont.push_back(*p); } +#if __cplusplus >= 201103L +template<> template<class Cont> void PackageContainer<std::forward_list<pkgCache::PkgIterator> >::insert(PackageContainer<Cont> const &pkgcont) { + for (typename PackageContainer<Cont>::const_iterator p = pkgcont.begin(); p != pkgcont.end(); ++p) + _cont.push_front(*p); +} +#endif +template<> template<class Cont> void PackageContainer<std::deque<pkgCache::PkgIterator> >::insert(PackageContainer<Cont> const &pkgcont) { + for (typename PackageContainer<Cont>::const_iterator p = pkgcont.begin(); p != pkgcont.end(); ++p) + _cont.push_back(*p); +} template<> template<class Cont> void PackageContainer<std::vector<pkgCache::PkgIterator> >::insert(PackageContainer<Cont> const &pkgcont) { for (typename PackageContainer<Cont>::const_iterator p = pkgcont.begin(); p != pkgcont.end(); ++p) _cont.push_back(*p); } -// these two are 'inline' as otherwise the linker has problems with seeing these untemplated +// these are 'inline' as otherwise the linker has problems with seeing these untemplated // specializations again and again - but we need to see them, so that library users can use them template<> inline bool PackageContainer<std::list<pkgCache::PkgIterator> >::insert(pkgCache::PkgIterator const &P) { if (P.end() == true) @@ -521,6 +606,20 @@ template<> inline bool PackageContainer<std::list<pkgCache::PkgIterator> >::inse _cont.push_back(P); return true; } +#if __cplusplus >= 201103L +template<> inline bool PackageContainer<std::forward_list<pkgCache::PkgIterator> >::insert(pkgCache::PkgIterator const &P) { + if (P.end() == true) + return false; + _cont.push_front(P); + return true; +} +#endif +template<> inline bool PackageContainer<std::deque<pkgCache::PkgIterator> >::insert(pkgCache::PkgIterator const &P) { + if (P.end() == true) + return false; + _cont.push_back(P); + return true; +} template<> inline bool PackageContainer<std::vector<pkgCache::PkgIterator> >::insert(pkgCache::PkgIterator const &P) { if (P.end() == true) return false; @@ -531,16 +630,49 @@ template<> inline void PackageContainer<std::list<pkgCache::PkgIterator> >::inse for (const_iterator p = begin; p != end; ++p) _cont.push_back(*p); } +#if __cplusplus >= 201103L +template<> inline void PackageContainer<std::forward_list<pkgCache::PkgIterator> >::insert(const_iterator begin, const_iterator end) { + for (const_iterator p = begin; p != end; ++p) + _cont.push_front(*p); +} +#endif +template<> inline void PackageContainer<std::deque<pkgCache::PkgIterator> >::insert(const_iterator begin, const_iterator end) { + for (const_iterator p = begin; p != end; ++p) + _cont.push_back(*p); +} template<> inline void PackageContainer<std::vector<pkgCache::PkgIterator> >::insert(const_iterator begin, const_iterator end) { for (const_iterator p = begin; p != end; ++p) _cont.push_back(*p); } - /*}}}*/ - +#if __cplusplus < 201103L +template<> inline PackageContainer<std::set<pkgCache::PkgIterator> >::iterator PackageContainer<std::set<pkgCache::PkgIterator> >::erase(iterator i) { + _cont.erase(i._iter); + return end(); +} +template<> inline PackageContainer<std::set<pkgCache::PkgIterator> >::iterator PackageContainer<std::set<pkgCache::PkgIterator> >::erase(iterator first, iterator last) { + _cont.erase(first, last); + return end(); +} +#endif template<> template<class Compare> inline bool PackageContainer<std::vector<pkgCache::PkgIterator> >::sort(Compare Comp) { std::sort(_cont.begin(), _cont.end(), Comp); return true; } +template<> template<class Compare> inline bool PackageContainer<std::list<pkgCache::PkgIterator> >::sort(Compare Comp) { + _cont.sort(Comp); + return true; +} +#if __cplusplus >= 201103L +template<> template<class Compare> inline bool PackageContainer<std::forward_list<pkgCache::PkgIterator> >::sort(Compare Comp) { + _cont.sort(Comp); + return true; +} +#endif +template<> template<class Compare> inline bool PackageContainer<std::deque<pkgCache::PkgIterator> >::sort(Compare Comp) { + std::sort(_cont.begin(), _cont.end(), Comp); + return true; +} + /*}}}*/ // class PackageUniverse - pkgCache as PackageContainerInterface /*{{{*/ /** \class PackageUniverse @@ -550,35 +682,53 @@ template<> template<class Compare> inline bool PackageContainer<std::vector<pkgC The wrapping is read-only in practice modeled by making erase and co private methods. */ -class APT_HIDDEN PackageUniverse : public PackageContainerInterface { +class APT_PUBLIC PackageUniverse : public PackageContainerInterface { pkgCache * const _cont; + void * const d; public: - typedef pkgCache::PkgIterator iterator; - typedef pkgCache::PkgIterator const_iterator; + class const_iterator : public APT::Container_iterator_base<APT::PackageContainerInterface, PackageUniverse, PackageUniverse::const_iterator, pkgCache::PkgIterator, pkgCache::PkgIterator> + { + public: + explicit const_iterator(pkgCache::PkgIterator i): + Container_iterator_base<APT::PackageContainerInterface, PackageUniverse, PackageUniverse::const_iterator, pkgCache::PkgIterator, pkgCache::PkgIterator>(i) {} + + inline pkgCache::PkgIterator getType(void) const { return _iter; } + }; + typedef const_iterator iterator; - APT_PUBLIC bool empty() const { return false; } - APT_PUBLIC size_t size() const { return _cont->Head().PackageCount; } + bool empty() const APT_OVERRIDE { return false; } + size_t size() const APT_OVERRIDE { return _cont->Head().PackageCount; } - APT_PUBLIC const_iterator begin() const { return _cont->PkgBegin(); } - APT_PUBLIC const_iterator end() const { return _cont->PkgEnd(); } - APT_PUBLIC iterator begin() { return _cont->PkgBegin(); } - APT_PUBLIC iterator end() { return _cont->PkgEnd(); } + const_iterator begin() const { return const_iterator(_cont->PkgBegin()); } + const_iterator end() const { return const_iterator(_cont->PkgEnd()); } + const_iterator cbegin() const { return const_iterator(_cont->PkgBegin()); } + const_iterator cend() const { return const_iterator(_cont->PkgEnd()); } + iterator begin() { return iterator(_cont->PkgBegin()); } + iterator end() { return iterator(_cont->PkgEnd()); } - APT_PUBLIC PackageUniverse(pkgCache * const Owner) : _cont(Owner) { } + pkgCache * data() const { return _cont; } + + explicit PackageUniverse(pkgCache * const Owner); + explicit PackageUniverse(pkgCacheFile * const Owner); + virtual ~PackageUniverse(); private: - bool insert(pkgCache::PkgIterator const &) { return true; } - template<class Cont> void insert(PackageContainer<Cont> const &) { } - void insert(const_iterator, const_iterator) { } - - void clear() { } - iterator& erase(iterator &iter) { return iter; } - size_t erase(const pkgCache::PkgIterator) { return 0; } - void erase(iterator, iterator) { } + APT_HIDDEN bool insert(pkgCache::PkgIterator const &) APT_OVERRIDE { return true; } + template<class Cont> APT_HIDDEN void insert(PackageContainer<Cont> const &) { } + APT_HIDDEN void insert(const_iterator, const_iterator) { } + + APT_HIDDEN void clear() APT_OVERRIDE { } + APT_HIDDEN iterator erase( const_iterator pos ); + APT_HIDDEN iterator erase( const_iterator first, const_iterator last ); }; /*}}}*/ typedef PackageContainer<std::set<pkgCache::PkgIterator> > PackageSet; +#if __cplusplus >= 201103L +typedef PackageContainer<std::unordered_set<pkgCache::PkgIterator> > PackageUnorderedSet; +typedef PackageContainer<std::forward_list<pkgCache::PkgIterator> > PackageForwardList; +#endif typedef PackageContainer<std::list<pkgCache::PkgIterator> > PackageList; +typedef PackageContainer<std::deque<pkgCache::PkgIterator> > PackageDeque; typedef PackageContainer<std::vector<pkgCache::PkgIterator> > PackageVector; class VersionContainerInterface { /*{{{*/ @@ -587,38 +737,39 @@ class VersionContainerInterface { /*{{{*/ Same as APT::PackageContainerInterface, just for Versions */ public: /** \brief smell like a pkgCache::VerIterator */ - class const_iterator { /*{{{*/ + template<class Itr> class iterator_base { /*{{{*/ + pkgCache::VerIterator getType() const { return static_cast<Itr const*>(this)->getType(); }; public: - virtual pkgCache::VerIterator getVer() const = 0; - operator pkgCache::VerIterator(void) { return getVer(); } - - inline pkgCache *Cache() const { return getVer().Cache(); } - inline unsigned long Index() const {return getVer().Index();} - inline int CompareVer(const pkgCache::VerIterator &B) const { return getVer().CompareVer(B); } - inline const char *VerStr() const { return getVer().VerStr(); } - inline const char *Section() const { return getVer().Section(); } - inline const char *Arch() const { return getVer().Arch(); } - inline pkgCache::PkgIterator ParentPkg() const { return getVer().ParentPkg(); } - inline pkgCache::DescIterator DescriptionList() const { return getVer().DescriptionList(); } - inline pkgCache::DescIterator TranslatedDescription() const { return getVer().TranslatedDescription(); } - inline pkgCache::DepIterator DependsList() const { return getVer().DependsList(); } - inline pkgCache::PrvIterator ProvidesList() const { return getVer().ProvidesList(); } - inline pkgCache::VerFileIterator FileList() const { return getVer().FileList(); } - inline bool Downloadable() const { return getVer().Downloadable(); } - inline const char *PriorityType() const { return getVer().PriorityType(); } - inline std::string RelStr() const { return getVer().RelStr(); } - inline bool Automatic() const { return getVer().Automatic(); } - inline pkgCache::VerFileIterator NewestFile() const { return getVer().NewestFile(); } + operator pkgCache::VerIterator(void) { return getType(); } + + inline pkgCache *Cache() const { return getType().Cache(); } + inline unsigned long Index() const {return getType().Index();} + inline int CompareVer(const pkgCache::VerIterator &B) const { return getType().CompareVer(B); } + inline const char *VerStr() const { return getType().VerStr(); } + inline const char *Section() const { return getType().Section(); } + inline const char *Arch() const { return getType().Arch(); } + inline pkgCache::PkgIterator ParentPkg() const { return getType().ParentPkg(); } + inline pkgCache::DescIterator DescriptionList() const { return getType().DescriptionList(); } + inline pkgCache::DescIterator TranslatedDescription() const { return getType().TranslatedDescription(); } + inline pkgCache::DepIterator DependsList() const { return getType().DependsList(); } + inline pkgCache::PrvIterator ProvidesList() const { return getType().ProvidesList(); } + inline pkgCache::VerFileIterator FileList() const { return getType().FileList(); } + inline bool Downloadable() const { return getType().Downloadable(); } + inline const char *PriorityType() const { return getType().PriorityType(); } + inline std::string RelStr() const { return getType().RelStr(); } + inline bool Automatic() const { return getType().Automatic(); } + inline pkgCache::VerFileIterator NewestFile() const { return getType().NewestFile(); } // we have only valid iterators here inline bool end() const { return false; } - inline pkgCache::Version const * operator->() const { return &*getVer(); } + inline pkgCache::Version const * operator->() const { return &*getType(); } }; /*}}}*/ virtual bool insert(pkgCache::VerIterator const &V) = 0; virtual bool empty() const = 0; virtual void clear() = 0; + virtual size_t size() const = 0; /** \brief specifies which version(s) will be returned if non is given */ enum APT_DEPRECATED Version { @@ -701,6 +852,12 @@ APT_IGNORE_DEPRECATED_PUSH } APT_IGNORE_DEPRECATED_POP + VersionContainerInterface(); + VersionContainerInterface& operator=(VersionContainerInterface const &other); + virtual ~VersionContainerInterface(); +private: + void * const d; + protected: /*{{{*/ /** \brief returns the candidate version of the package @@ -729,56 +886,38 @@ template<class Container> class VersionContainer : public VersionContainerInterf pkgCache. */ Container _cont; public: /*{{{*/ - /** \brief smell like a pkgCache::VerIterator */ - class const_iterator : public VersionContainerInterface::const_iterator, - public std::iterator<std::forward_iterator_tag, typename Container::const_iterator> {/*{{{*/ - typename Container::const_iterator _iter; - public: - const_iterator(typename Container::const_iterator i) : _iter(i) {} - pkgCache::VerIterator getVer(void) const { return *_iter; } - inline pkgCache::VerIterator operator*(void) const { return *_iter; } - operator typename Container::const_iterator(void) const { return _iter; } - inline const_iterator& operator++() { ++_iter; return *this; } - inline const_iterator operator++(int) { const_iterator tmp(*this); operator++(); return tmp; } - inline bool operator!=(const_iterator const &i) const { return _iter != i._iter; } - inline bool operator==(const_iterator const &i) const { return _iter == i._iter; } - friend std::ostream& operator<<(std::ostream& out, const_iterator i) { return operator<<(out, *i); } - }; - class iterator : public VersionContainerInterface::const_iterator, - public std::iterator<std::forward_iterator_tag, typename Container::iterator> { - typename Container::iterator _iter; - public: - iterator(typename Container::iterator i) : _iter(i) {} - pkgCache::VerIterator getVer(void) const { return *_iter; } - inline pkgCache::VerIterator operator*(void) const { return *_iter; } - operator typename Container::iterator(void) const { return _iter; } - operator typename VersionContainer<Container>::const_iterator() { return typename VersionContainer<Container>::const_iterator(_iter); } - inline iterator& operator++() { ++_iter; return *this; } - inline iterator operator++(int) { iterator tmp(*this); operator++(); return tmp; } - inline bool operator!=(iterator const &i) const { return _iter != i._iter; } - inline bool operator==(iterator const &i) const { return _iter == i._iter; } - inline iterator& operator=(iterator const &i) { _iter = i._iter; return *this; } - inline iterator& operator=(typename Container::iterator const &i) { _iter = i; return *this; } - friend std::ostream& operator<<(std::ostream& out, iterator i) { return operator<<(out, *i); } - }; - /*}}}*/ + typedef Container_const_iterator<VersionContainerInterface, Container, VersionContainer> const_iterator; + typedef Container_iterator<VersionContainerInterface, Container, VersionContainer> iterator; + typedef Container_const_reverse_iterator<VersionContainerInterface, Container, VersionContainer> const_reverse_iterator; + typedef Container_reverse_iterator<VersionContainerInterface, Container, VersionContainer> reverse_iterator; - bool insert(pkgCache::VerIterator const &V) { if (V.end() == true) return false; _cont.insert(V); return true; } + bool insert(pkgCache::VerIterator const &V) APT_OVERRIDE { if (V.end() == true) return false; _cont.insert(V); return true; } template<class Cont> void insert(VersionContainer<Cont> const &vercont) { _cont.insert((typename Cont::const_iterator)vercont.begin(), (typename Cont::const_iterator)vercont.end()); } void insert(const_iterator begin, const_iterator end) { _cont.insert(begin, end); } - bool empty() const { return _cont.empty(); } - void clear() { return _cont.clear(); } - //FIXME: on ABI break, replace the first with the second without bool - void erase(iterator position) { _cont.erase((typename Container::iterator)position); } - iterator& erase(iterator &position, bool) { return position = _cont.erase((typename Container::iterator)position); } - size_t erase(const pkgCache::VerIterator x) { return _cont.erase(x); } - void erase(iterator first, iterator last) { _cont.erase(first, last); } - size_t size() const { return _cont.size(); } - + bool empty() const APT_OVERRIDE { return _cont.empty(); } + void clear() APT_OVERRIDE { return _cont.clear(); } + size_t size() const APT_OVERRIDE { return _cont.size(); } +#if __GNUC__ >= 5 || (__GNUC_MINOR__ >= 9 && __GNUC__ >= 4) + iterator erase( const_iterator pos ) { return iterator(_cont.erase(pos._iter)); } + iterator erase( const_iterator first, const_iterator last ) { return iterator(_cont.erase(first._iter, last._iter)); } +#else + iterator erase( iterator pos ) { return iterator(_cont.erase(pos._iter)); } + iterator erase( iterator first, iterator last ) { return iterator(_cont.erase(first._iter, last._iter)); } +#endif const_iterator begin() const { return const_iterator(_cont.begin()); } const_iterator end() const { return const_iterator(_cont.end()); } + const_reverse_iterator rbegin() const { return const_reverse_iterator(_cont.rbegin()); } + const_reverse_iterator rend() const { return const_reverse_iterator(_cont.rend()); } +#if __cplusplus >= 201103L + const_iterator cbegin() const { return const_iterator(_cont.cbegin()); } + const_iterator cend() const { return const_iterator(_cont.cend()); } + const_reverse_iterator crbegin() const { return const_reverse_iterator(_cont.crbegin()); } + const_reverse_iterator crend() const { return const_reverse_iterator(_cont.crend()); } +#endif iterator begin() { return iterator(_cont.begin()); } iterator end() { return iterator(_cont.end()); } + reverse_iterator rbegin() { return reverse_iterator(_cont.rbegin()); } + reverse_iterator rend() { return reverse_iterator(_cont.rend()); } const_iterator find(pkgCache::VerIterator const &V) const { return const_iterator(_cont.find(V)); } /** \brief sort all included versions with given comparer @@ -924,7 +1063,7 @@ APT_IGNORE_DEPRECATED_POP static VersionContainer FromDependency(pkgCacheFile &Cache, pkgCache::DepIterator const &D, CacheSetHelper::VerSelector const selector) { CacheSetHelper helper; - return FromPackage(Cache, D, selector, helper); + return FromDependency(Cache, D, selector, helper); } APT_IGNORE_DEPRECATED_PUSH static VersionContainer FromDependency(pkgCacheFile &Cache, pkgCache::DepIterator const &D, @@ -936,24 +1075,34 @@ APT_IGNORE_DEPRECATED_PUSH static VersionContainer FromDependency(pkgCacheFile &Cache, pkgCache::DepIterator const &D, Version const &selector) { CacheSetHelper helper; - return FromPackage(Cache, D, (CacheSetHelper::VerSelector)selector, helper); + return FromDependency(Cache, D, (CacheSetHelper::VerSelector)selector, helper); } APT_IGNORE_DEPRECATED_POP static VersionContainer FromDependency(pkgCacheFile &Cache, pkgCache::DepIterator const &D) { - return FromPackage(Cache, D, CacheSetHelper::CANDIDATE); + return FromDependency(Cache, D, CacheSetHelper::CANDIDATE); } /*}}}*/ }; /*}}}*/ -// specialisations for push_back containers: std::list & std::vector /*{{{*/ +// various specialisations for VersionContainer /*{{{*/ template<> template<class Cont> void VersionContainer<std::list<pkgCache::VerIterator> >::insert(VersionContainer<Cont> const &vercont) { for (typename VersionContainer<Cont>::const_iterator v = vercont.begin(); v != vercont.end(); ++v) _cont.push_back(*v); } +#if __cplusplus >= 201103L +template<> template<class Cont> void VersionContainer<std::forward_list<pkgCache::VerIterator> >::insert(VersionContainer<Cont> const &vercont) { + for (typename VersionContainer<Cont>::const_iterator v = vercont.begin(); v != vercont.end(); ++v) + _cont.push_front(*v); +} +#endif +template<> template<class Cont> void VersionContainer<std::deque<pkgCache::VerIterator> >::insert(VersionContainer<Cont> const &vercont) { + for (typename VersionContainer<Cont>::const_iterator v = vercont.begin(); v != vercont.end(); ++v) + _cont.push_back(*v); +} template<> template<class Cont> void VersionContainer<std::vector<pkgCache::VerIterator> >::insert(VersionContainer<Cont> const &vercont) { for (typename VersionContainer<Cont>::const_iterator v = vercont.begin(); v != vercont.end(); ++v) _cont.push_back(*v); } -// these two are 'inline' as otherwise the linker has problems with seeing these untemplated +// these are 'inline' as otherwise the linker has problems with seeing these untemplated // specializations again and again - but we need to see them, so that library users can use them template<> inline bool VersionContainer<std::list<pkgCache::VerIterator> >::insert(pkgCache::VerIterator const &V) { if (V.end() == true) @@ -961,6 +1110,20 @@ template<> inline bool VersionContainer<std::list<pkgCache::VerIterator> >::inse _cont.push_back(V); return true; } +#if __cplusplus >= 201103L +template<> inline bool VersionContainer<std::forward_list<pkgCache::VerIterator> >::insert(pkgCache::VerIterator const &V) { + if (V.end() == true) + return false; + _cont.push_front(V); + return true; +} +#endif +template<> inline bool VersionContainer<std::deque<pkgCache::VerIterator> >::insert(pkgCache::VerIterator const &V) { + if (V.end() == true) + return false; + _cont.push_back(V); + return true; +} template<> inline bool VersionContainer<std::vector<pkgCache::VerIterator> >::insert(pkgCache::VerIterator const &V) { if (V.end() == true) return false; @@ -971,19 +1134,57 @@ template<> inline void VersionContainer<std::list<pkgCache::VerIterator> >::inse for (const_iterator v = begin; v != end; ++v) _cont.push_back(*v); } +#if __cplusplus >= 201103L +template<> inline void VersionContainer<std::forward_list<pkgCache::VerIterator> >::insert(const_iterator begin, const_iterator end) { + for (const_iterator v = begin; v != end; ++v) + _cont.push_front(*v); +} +#endif +template<> inline void VersionContainer<std::deque<pkgCache::VerIterator> >::insert(const_iterator begin, const_iterator end) { + for (const_iterator v = begin; v != end; ++v) + _cont.push_back(*v); +} template<> inline void VersionContainer<std::vector<pkgCache::VerIterator> >::insert(const_iterator begin, const_iterator end) { for (const_iterator v = begin; v != end; ++v) _cont.push_back(*v); } - /*}}}*/ - +#if __cplusplus < 201103L +template<> inline VersionContainer<std::set<pkgCache::VerIterator> >::iterator VersionContainer<std::set<pkgCache::VerIterator> >::erase(iterator i) { + _cont.erase(i._iter); + return end(); +} +template<> inline VersionContainer<std::set<pkgCache::VerIterator> >::iterator VersionContainer<std::set<pkgCache::VerIterator> >::erase(iterator first, iterator last) { + _cont.erase(first, last); + return end(); +} +#endif template<> template<class Compare> inline bool VersionContainer<std::vector<pkgCache::VerIterator> >::sort(Compare Comp) { std::sort(_cont.begin(), _cont.end(), Comp); return true; } +template<> template<class Compare> inline bool VersionContainer<std::list<pkgCache::VerIterator> >::sort(Compare Comp) { + _cont.sort(Comp); + return true; +} +#if __cplusplus >= 201103L +template<> template<class Compare> inline bool VersionContainer<std::forward_list<pkgCache::VerIterator> >::sort(Compare Comp) { + _cont.sort(Comp); + return true; +} +#endif +template<> template<class Compare> inline bool VersionContainer<std::deque<pkgCache::VerIterator> >::sort(Compare Comp) { + std::sort(_cont.begin(), _cont.end(), Comp); + return true; +} + /*}}}*/ typedef VersionContainer<std::set<pkgCache::VerIterator> > VersionSet; +#if __cplusplus >= 201103L +typedef VersionContainer<std::unordered_set<pkgCache::VerIterator> > VersionUnorderedSet; +typedef VersionContainer<std::forward_list<pkgCache::VerIterator> > VersionForwardList; +#endif typedef VersionContainer<std::list<pkgCache::VerIterator> > VersionList; +typedef VersionContainer<std::deque<pkgCache::VerIterator> > VersionDeque; typedef VersionContainer<std::vector<pkgCache::VerIterator> > VersionVector; } #endif diff --git a/apt-pkg/cdrom.cc b/apt-pkg/cdrom.cc index 8cec4b78e..dea4a88c3 100644 --- a/apt-pkg/cdrom.cc +++ b/apt-pkg/cdrom.cc @@ -16,14 +16,15 @@ #include <iostream> #include <string> #include <vector> -#include <sstream> -#include <fstream> #include <sys/stat.h> #include <dirent.h> #include <unistd.h> #include <stdio.h> #include <algorithm> #include <dlfcn.h> +#include <iostream> +#include <sstream> +#include <fstream> #include<apti18n.h> @@ -917,7 +918,7 @@ bool pkgCdrom::Add(pkgCdromStatus *log) /*{{{*/ } /*}}}*/ pkgUdevCdromDevices::pkgUdevCdromDevices() /*{{{*/ -: libudev_handle(NULL), udev_new(NULL), udev_enumerate_add_match_property(NULL), +: d(NULL), libudev_handle(NULL), udev_new(NULL), udev_enumerate_add_match_property(NULL), udev_enumerate_scan_devices(NULL), udev_enumerate_get_list_entry(NULL), udev_device_new_from_syspath(NULL), udev_enumerate_get_udev(NULL), udev_list_entry_get_name(NULL), udev_device_get_devnode(NULL), @@ -1022,3 +1023,9 @@ pkgUdevCdromDevices::~pkgUdevCdromDevices() /*{{{*/ dlclose(libudev_handle); } /*}}}*/ + +pkgCdromStatus::pkgCdromStatus() : d(NULL), totalSteps(0) {} +pkgCdromStatus::~pkgCdromStatus() {} + +pkgCdrom::pkgCdrom() : d(NULL) {} +pkgCdrom::~pkgCdrom() {} diff --git a/apt-pkg/cdrom.h b/apt-pkg/cdrom.h index bd0902176..ab1e046bf 100644 --- a/apt-pkg/cdrom.h +++ b/apt-pkg/cdrom.h @@ -18,12 +18,13 @@ class OpProgress; class pkgCdromStatus /*{{{*/ { + void * const d; protected: int totalSteps; public: - pkgCdromStatus() : totalSteps(0) {}; - virtual ~pkgCdromStatus() {}; + pkgCdromStatus(); + virtual ~pkgCdromStatus(); // total steps virtual void SetTotal(int total) { totalSteps = total; }; @@ -74,7 +75,12 @@ class pkgCdrom /*{{{*/ bool Ident(std::string &ident, pkgCdromStatus *log); bool Add(pkgCdromStatus *log); + pkgCdrom(); + virtual ~pkgCdrom(); + private: + void * const d; + APT_HIDDEN bool MountAndIdentCDROM(Configuration &Database, std::string &CDROM, std::string &ident, pkgCdromStatus * const log, bool const interactive); APT_HIDDEN bool UnmountCDROM(std::string const &CDROM, pkgCdromStatus * const log); @@ -92,6 +98,7 @@ struct CdromDevice /*{{{*/ /*}}}*/ class pkgUdevCdromDevices /*{{{*/ { + void * const d; protected: // libudev dlopen structure void *libudev_handle; diff --git a/apt-pkg/clean.cc b/apt-pkg/clean.cc index 6edce5b6d..ebe8a8a53 100644 --- a/apt-pkg/clean.cc +++ b/apt-pkg/clean.cc @@ -106,7 +106,7 @@ bool pkgArchiveCleaner::Go(std::string Dir,pkgCache &Cache) J.end() == false; ++J) { if (CleanInstalled == true && - (J.File()->Flags & pkgCache::Flag::NotSource) != 0) + J.File().Flagged(pkgCache::Flag::NotSource)) continue; IsFetchable = true; break; @@ -132,4 +132,5 @@ bool pkgArchiveCleaner::Go(std::string Dir,pkgCache &Cache) } /*}}}*/ +pkgArchiveCleaner::pkgArchiveCleaner() : d(NULL) {} APT_CONST pkgArchiveCleaner::~pkgArchiveCleaner() {} diff --git a/apt-pkg/clean.h b/apt-pkg/clean.h index 466cb67a9..6cedae086 100644 --- a/apt-pkg/clean.h +++ b/apt-pkg/clean.h @@ -21,7 +21,7 @@ class pkgCache; class pkgArchiveCleaner { /** \brief dpointer placeholder (for later in case we need it) */ - void *d; + void * const d; protected: @@ -30,6 +30,8 @@ class pkgArchiveCleaner public: bool Go(std::string Dir,pkgCache &Cache); + + pkgArchiveCleaner(); virtual ~pkgArchiveCleaner(); }; diff --git a/apt-pkg/contrib/cdromutl.cc b/apt-pkg/contrib/cdromutl.cc index 6eb917457..428ef0161 100644 --- a/apt-pkg/contrib/cdromutl.cc +++ b/apt-pkg/contrib/cdromutl.cc @@ -287,9 +287,11 @@ string FindMountPointForDevice(const char *devnode) fclose(f); // unescape the \0XXX chars in the path string mount_point = out[1]; + free(line); return DeEscapeString(mount_point); } fclose(f); + free(line); } return string(); diff --git a/apt-pkg/contrib/cmndline.cc b/apt-pkg/contrib/cmndline.cc index ff8b09ebc..40365237e 100644 --- a/apt-pkg/contrib/cmndline.cc +++ b/apt-pkg/contrib/cmndline.cc @@ -124,7 +124,7 @@ bool CommandLine::Parse(int argc,const char **argv) Args *A; for (A = ArgList; A->end() == false && A->ShortOpt != *Opt; A++); if (A->end() == true) - return _error->Error(_("Command line option '%c' [from %s] is not known."),*Opt,argv[I]); + return _error->Error(_("Command line option '%c' [from %s] is not understood in combination with the other options."),*Opt,argv[I]); if (HandleOpt(I,argc,argv,Opt,A) == false) return false; @@ -149,7 +149,7 @@ bool CommandLine::Parse(int argc,const char **argv) { Opt = (const char*) memchr(Opt, '-', OptEnd - Opt); if (Opt == NULL) - return _error->Error(_("Command line option %s is not understood"),argv[I]); + return _error->Error(_("Command line option %s is not understood in combination with the other options"),argv[I]); Opt++; for (A = ArgList; A->end() == false && @@ -158,7 +158,7 @@ bool CommandLine::Parse(int argc,const char **argv) // Failed again.. if (A->end() == true && OptEnd - Opt != 1) - return _error->Error(_("Command line option %s is not understood"),argv[I]); + return _error->Error(_("Command line option %s is not understood in combination with the other options"),argv[I]); // The option could be a single letter option prefixed by a no-.. if (A->end() == true) @@ -166,7 +166,7 @@ bool CommandLine::Parse(int argc,const char **argv) for (A = ArgList; A->end() == false && A->ShortOpt != *Opt; A++); if (A->end() == true) - return _error->Error(_("Command line option %s is not understood"),argv[I]); + return _error->Error(_("Command line option %s is not understood in combination with the other options"),argv[I]); } // The option is not boolean diff --git a/apt-pkg/contrib/configuration.cc b/apt-pkg/contrib/configuration.cc index 42e35d32a..203de158b 100644 --- a/apt-pkg/contrib/configuration.cc +++ b/apt-pkg/contrib/configuration.cc @@ -253,13 +253,7 @@ string Configuration::FindDir(const char *Name,const char *Default) const // Configuration::FindVector - Find a vector of values /*{{{*/ // --------------------------------------------------------------------- /* Returns a vector of config values under the given item */ -#if APT_PKG_ABI < 413 -vector<string> Configuration::FindVector(const char *Name) const -{ - return FindVector(Name, ""); -} -#endif -vector<string> Configuration::FindVector(const char *Name, std::string const &Default) const +vector<string> Configuration::FindVector(const char *Name, std::string const &Default, bool const Keys) const { vector<string> Vec; const Item *Top = Lookup(Name); @@ -272,7 +266,7 @@ vector<string> Configuration::FindVector(const char *Name, std::string const &De Item *I = Top->Child; while(I != NULL) { - Vec.push_back(I->Value); + Vec.push_back(Keys ? I->Tag : I->Value); I = I->Next; } if (Vec.empty() == true) diff --git a/apt-pkg/contrib/configuration.h b/apt-pkg/contrib/configuration.h index 8d7d51037..eacc26fda 100644 --- a/apt-pkg/contrib/configuration.h +++ b/apt-pkg/contrib/configuration.h @@ -84,15 +84,8 @@ class Configuration * * \param Name of the parent node * \param Default list of values separated by commas */ -#if APT_PKG_ABI >= 413 - std::vector<std::string> FindVector(const char *Name, std::string const &Default = "") const; - std::vector<std::string> FindVector(std::string const &Name, std::string const &Default = "") const { return FindVector(Name.c_str(), Default); }; -#else - std::vector<std::string> FindVector(const char *Name, std::string const &Default) const; - std::vector<std::string> FindVector(std::string const &Name, std::string const &Default) const { return FindVector(Name.c_str(), Default); }; - std::vector<std::string> FindVector(const char *Name) const; - std::vector<std::string> FindVector(std::string const &Name) const { return FindVector(Name.c_str(), ""); }; -#endif + std::vector<std::string> FindVector(const char *Name, std::string const &Default = "", bool const Keys = false) const; + std::vector<std::string> FindVector(std::string const &Name, std::string const &Default = "", bool const Keys = false) const { return FindVector(Name.c_str(), Default, Keys); }; int FindI(const char *Name,int const &Default = 0) const; int FindI(std::string const &Name,int const &Default = 0) const {return FindI(Name.c_str(),Default);}; diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 8ec868ec0..1be782bac 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -52,6 +52,7 @@ #include <set> #include <algorithm> +#include <memory> #ifdef HAVE_ZLIB #include <zlib.h> @@ -159,7 +160,7 @@ bool CopyFile(FileFd &From,FileFd &To) return false; // Buffered copy between fds - SPtrArray<unsigned char> Buf = new unsigned char[64000]; + std::unique_ptr<unsigned char[]> Buf(new unsigned char[64000]); unsigned long long Size = From.Size(); while (Size != 0) { @@ -167,8 +168,8 @@ bool CopyFile(FileFd &From,FileFd &To) if (Size > 64000) ToRead = 64000; - if (From.Read(Buf,ToRead) == false || - To.Write(Buf,ToRead) == false) + if (From.Read(Buf.get(),ToRead) == false || + To.Write(Buf.get(),ToRead) == false) return false; Size -= ToRead; @@ -800,12 +801,26 @@ pid_t ExecFork(std::set<int> KeepFDs) signal(SIGCONT,SIG_DFL); signal(SIGTSTP,SIG_DFL); - long ScOpenMax = sysconf(_SC_OPEN_MAX); - // Close all of our FDs - just in case - for (int K = 3; K != ScOpenMax; K++) + DIR *dir = opendir("/proc/self/fd"); + if (dir != NULL) { - if(KeepFDs.find(K) == KeepFDs.end()) - fcntl(K,F_SETFD,FD_CLOEXEC); + struct dirent *ent; + while ((ent = readdir(dir))) + { + int fd = atoi(ent->d_name); + // If fd > 0, it was a fd number and not . or .. + if (fd >= 3 && KeepFDs.find(fd) == KeepFDs.end()) + fcntl(fd,F_SETFD,FD_CLOEXEC); + } + closedir(dir); + } else { + long ScOpenMax = sysconf(_SC_OPEN_MAX); + // Close all of our FDs - just in case + for (int K = 3; K != ScOpenMax; K++) + { + if(KeepFDs.find(K) == KeepFDs.end()) + fcntl(K,F_SETFD,FD_CLOEXEC); + } } } @@ -1011,6 +1026,25 @@ class FileFdPrivate { /*{{{*/ ~FileFdPrivate() { CloseDown(""); } }; /*}}}*/ +// FileFd Constructors /*{{{*/ +FileFd::FileFd(std::string FileName,unsigned int const Mode,unsigned long AccessMode) : iFd(-1), Flags(0), d(NULL) +{ + Open(FileName,Mode, None, AccessMode); +} +FileFd::FileFd(std::string FileName,unsigned int const Mode, CompressMode Compress, unsigned long AccessMode) : iFd(-1), Flags(0), d(NULL) +{ + Open(FileName,Mode, Compress, AccessMode); +} +FileFd::FileFd() : iFd(-1), Flags(AutoClose), d(NULL) {} +FileFd::FileFd(int const Fd, unsigned int const Mode, CompressMode Compress) : iFd(-1), Flags(0), d(NULL) +{ + OpenDescriptor(Fd, Mode, Compress); +} +FileFd::FileFd(int const Fd, bool const AutoClose) : iFd(-1), Flags(0), d(NULL) +{ + OpenDescriptor(Fd, ReadWrite, None, AutoClose); +} + /*}}}*/ // FileFd::Open - Open a file /*{{{*/ // --------------------------------------------------------------------- /* The most commonly used open mode combinations are given with Mode */ @@ -2096,28 +2130,27 @@ std::string GetTempDir() /*{{{*/ return string(tmpdir); } /*}}}*/ -FileFd* GetTempFile(std::string const &Prefix, bool ImmediateUnlink) /*{{{*/ +FileFd* GetTempFile(std::string const &Prefix, bool ImmediateUnlink, FileFd * const TmpFd) /*{{{*/ { char fn[512]; - FileFd *Fd = new FileFd(); + FileFd * const Fd = TmpFd == NULL ? new FileFd() : TmpFd; - std::string tempdir = GetTempDir(); - snprintf(fn, sizeof(fn), "%s/%s.XXXXXX", + std::string const tempdir = GetTempDir(); + snprintf(fn, sizeof(fn), "%s/%s.XXXXXX", tempdir.c_str(), Prefix.c_str()); - int fd = mkstemp(fn); + int const fd = mkstemp(fn); if(ImmediateUnlink) unlink(fn); - if (fd < 0) + if (fd < 0) { _error->Errno("GetTempFile",_("Unable to mkstemp %s"), fn); return NULL; } - if (!Fd->OpenDescriptor(fd, FileFd::WriteOnly, FileFd::None, true)) + if (!Fd->OpenDescriptor(fd, FileFd::ReadWrite, FileFd::None, true)) { _error->Errno("GetTempFile",_("Unable to write to %s"),fn); return NULL; } - return Fd; } /*}}}*/ @@ -2219,22 +2252,32 @@ bool DropPrivileges() /*{{{*/ return _error->Error("No user %s, can not drop rights", toUser.c_str()); // Do not change the order here, it might break things + // Get rid of all our supplementary groups first if (setgroups(1, &pw->pw_gid)) return _error->Errno("setgroups", "Failed to setgroups"); + // Now change the group ids to the new user +#ifdef HAVE_SETRESGID + if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) + return _error->Errno("setresgid", "Failed to set new group ids"); +#else if (setegid(pw->pw_gid) != 0) return _error->Errno("setegid", "Failed to setegid"); if (setgid(pw->pw_gid) != 0) return _error->Errno("setgid", "Failed to setgid"); +#endif + // Change the user ids to the new user +#ifdef HAVE_SETRESUID + if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) + return _error->Errno("setresuid", "Failed to set new user ids"); +#else if (setuid(pw->pw_uid) != 0) return _error->Errno("setuid", "Failed to setuid"); - - // the seteuid() is probably uneeded (at least thats what the linux - // man-page says about setuid(2)) but we cargo culted it anyway if (seteuid(pw->pw_uid) != 0) return _error->Errno("seteuid", "Failed to seteuid"); +#endif // Verify that the user has only a single group, and the correct one gid_t groups[1]; diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h index 97cb05c56..acfd560ab 100644 --- a/apt-pkg/contrib/fileutl.h +++ b/apt-pkg/contrib/fileutl.h @@ -130,28 +130,17 @@ class FileFd inline bool Eof() {return (Flags & HitEof) == HitEof;}; inline bool IsCompressed() {return (Flags & Compressed) == Compressed;}; inline std::string &Name() {return FileName;}; - - FileFd(std::string FileName,unsigned int const Mode,unsigned long AccessMode = 0666) : iFd(-1), Flags(0), d(NULL) - { - Open(FileName,Mode, None, AccessMode); - }; - FileFd(std::string FileName,unsigned int const Mode, CompressMode Compress, unsigned long AccessMode = 0666) : iFd(-1), Flags(0), d(NULL) - { - Open(FileName,Mode, Compress, AccessMode); - }; - FileFd() : iFd(-1), Flags(AutoClose), d(NULL) {}; - FileFd(int const Fd, unsigned int const Mode = ReadWrite, CompressMode Compress = None) : iFd(-1), Flags(0), d(NULL) - { - OpenDescriptor(Fd, Mode, Compress); - }; - FileFd(int const Fd, bool const AutoClose) : iFd(-1), Flags(0), d(NULL) - { - OpenDescriptor(Fd, ReadWrite, None, AutoClose); - }; + + FileFd(std::string FileName,unsigned int const Mode,unsigned long AccessMode = 0666); + FileFd(std::string FileName,unsigned int const Mode, CompressMode Compress, unsigned long AccessMode = 0666); + FileFd(); + FileFd(int const Fd, unsigned int const Mode = ReadWrite, CompressMode Compress = None); + FileFd(int const Fd, bool const AutoClose); virtual ~FileFd(); private: - FileFdPrivate* d; + FileFdPrivate * d; + APT_HIDDEN FileFd & operator=(const FileFd &); APT_HIDDEN bool OpenInternDescriptor(unsigned int const Mode, APT::Configuration::Compressor const &compressor); // private helpers to set Fail flag and call _error->Error @@ -170,8 +159,9 @@ time_t GetModificationTime(std::string const &Path); bool Rename(std::string From, std::string To); std::string GetTempDir(); -FileFd* GetTempFile(std::string const &Prefix = "", - bool ImmediateUnlink = true); +FileFd* GetTempFile(std::string const &Prefix = "", + bool ImmediateUnlink = true, + FileFd * const TmpFd = NULL); /** \brief Ensure the existence of the given Path * diff --git a/apt-pkg/contrib/gpgv.cc b/apt-pkg/contrib/gpgv.cc index 9d798cca9..ef84da0d8 100644 --- a/apt-pkg/contrib/gpgv.cc +++ b/apt-pkg/contrib/gpgv.cc @@ -16,6 +16,8 @@ #include <sys/wait.h> #include <unistd.h> #include <stddef.h> + +#include <algorithm> #include <iostream> #include <string> #include <vector> @@ -42,7 +44,7 @@ static char * GenerateTemporaryFileTemplate(const char *basename) /*{{{*/ of the lifting in regards to merging keyrings. Fun for the whole family. */ void ExecGPGV(std::string const &File, std::string const &FileGPG, - int const &statusfd, int fd[2]) + int const &statusfd, int fd[2], std::string const &key) { #define EINTERNAL 111 std::string const aptkey = _config->FindFile("Dir::Bin::apt-key", "/usr/bin/apt-key"); @@ -55,6 +57,19 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG, Args.push_back(aptkey.c_str()); Args.push_back("--quiet"); Args.push_back("--readonly"); + if (key.empty() == false) + { + if (key[0] == '/') + { + Args.push_back("--keyring"); + Args.push_back(key.c_str()); + } + else + { + Args.push_back("--keyid"); + Args.push_back(key.c_str()); + } + } Args.push_back("verify"); char statusfdstr[10]; @@ -296,6 +311,8 @@ bool SplitClearSignedFile(std::string const &InFile, FileFd * const ContentFile, // all the rest is whitespace, unsigned garbage or additional message blocks we ignore } fclose(in); + if (buf != NULL) + free(buf); if (found_signature == true) return _error->Error("Signature in file %s wasn't closed", InFile.c_str()); diff --git a/apt-pkg/contrib/gpgv.h b/apt-pkg/contrib/gpgv.h index f018893fd..2a4cdad72 100644 --- a/apt-pkg/contrib/gpgv.h +++ b/apt-pkg/contrib/gpgv.h @@ -38,9 +38,12 @@ class FileFd; * * @param File is the message (unsigned or clear-signed) * @param FileSig is the signature (detached or clear-signed) + * @param statusfd is the fd given to gpgv as --status-fd + * @param fd is used as a pipe for the standard output of gpgv + * @param key is the specific one to be used instead of using all */ void ExecGPGV(std::string const &File, std::string const &FileSig, - int const &statusfd, int fd[2]) APT_NORETURN; + int const &statusfd, int fd[2], std::string const &Key = "") APT_NORETURN; inline APT_NORETURN void ExecGPGV(std::string const &File, std::string const &FileSig, int const &statusfd = -1) { int fd[2]; diff --git a/apt-pkg/contrib/hashes.cc b/apt-pkg/contrib/hashes.cc index 0fa443b4a..4481321c4 100644 --- a/apt-pkg/contrib/hashes.cc +++ b/apt-pkg/contrib/hashes.cc @@ -23,6 +23,7 @@ #include <stddef.h> #include <algorithm> #include <unistd.h> +#include <stdlib.h> #include <string> #include <iostream> /*}}}*/ @@ -178,6 +179,22 @@ HashString const * HashStringList::find(char const * const type) const /*{{{*/ return NULL; } /*}}}*/ +unsigned long long HashStringList::FileSize() const /*{{{*/ +{ + HashString const * const hsf = find("Checksum-FileSize"); + if (hsf == NULL) + return 0; + std::string const hv = hsf->HashValue(); + return strtoull(hv.c_str(), NULL, 10); +} + /*}}}*/ +bool HashStringList::FileSize(unsigned long long const Size) /*{{{*/ +{ + std::string size; + strprintf(size, "%llu", Size); + return push_back(HashString("Checksum-FileSize", size)); +} + /*}}}*/ bool HashStringList::supported(char const * const type) /*{{{*/ { for (char const * const * t = HashString::SupportedHashes(); *t != NULL; ++t) @@ -259,7 +276,19 @@ public: unsigned long long FileSize; unsigned int CalcHashes; - PrivateHashes(unsigned int const CalcHashes) : FileSize(0), CalcHashes(CalcHashes) {} + explicit PrivateHashes(unsigned int const CalcHashes) : FileSize(0), CalcHashes(CalcHashes) {} + explicit PrivateHashes(HashStringList const &Hashes) : FileSize(0) { + unsigned int calcHashes = Hashes.usable() ? 0 : ~0; + if (Hashes.find("MD5Sum") != NULL) + calcHashes |= Hashes::MD5SUM; + if (Hashes.find("SHA1") != NULL) + calcHashes |= Hashes::SHA1SUM; + if (Hashes.find("SHA256") != NULL) + calcHashes |= Hashes::SHA256SUM; + if (Hashes.find("SHA512") != NULL) + calcHashes |= Hashes::SHA512SUM; + CalcHashes = calcHashes; + } }; /*}}}*/ // Hashes::Add* - Add the contents of data or FD /*{{{*/ @@ -351,25 +380,12 @@ APT_IGNORE_DEPRECATED_PUSH if ((d->CalcHashes & SHA512SUM) == SHA512SUM) hashes.push_back(HashString("SHA512", SHA512.Result().Value())); APT_IGNORE_DEPRECATED_POP - std::string SizeStr; - strprintf(SizeStr, "%llu", d->FileSize); - hashes.push_back(HashString("Checksum-FileSize", SizeStr)); + hashes.FileSize(d->FileSize); return hashes; } APT_IGNORE_DEPRECATED_PUSH -Hashes::Hashes() { d = new PrivateHashes(~0); } -Hashes::Hashes(unsigned int const Hashes) { d = new PrivateHashes(Hashes); } -Hashes::Hashes(HashStringList const &Hashes) { - unsigned int calcHashes = Hashes.usable() ? 0 : ~0; - if (Hashes.find("MD5Sum") != NULL) - calcHashes |= MD5SUM; - if (Hashes.find("SHA1") != NULL) - calcHashes |= SHA1SUM; - if (Hashes.find("SHA256") != NULL) - calcHashes |= SHA256SUM; - if (Hashes.find("SHA512") != NULL) - calcHashes |= SHA512SUM; - d = new PrivateHashes(calcHashes); -} +Hashes::Hashes() : d(new PrivateHashes(~0)) { } +Hashes::Hashes(unsigned int const Hashes) : d(new PrivateHashes(Hashes)) {} +Hashes::Hashes(HashStringList const &Hashes) : d(new PrivateHashes(Hashes)) {} Hashes::~Hashes() { delete d; } APT_IGNORE_DEPRECATED_POP diff --git a/apt-pkg/contrib/hashes.h b/apt-pkg/contrib/hashes.h index ac13c8ace..0e6ff9ef1 100644 --- a/apt-pkg/contrib/hashes.h +++ b/apt-pkg/contrib/hashes.h @@ -87,6 +87,22 @@ class HashStringList */ HashString const * find(char const * const type) const; HashString const * find(std::string const &type) const { return find(type.c_str()); } + + /** finds the filesize hash and returns it as number + * + * @return beware: if the size isn't known we return \b 0 here, + * just like we would do for an empty file. If that is a problem + * for you have to get the size manually out of the list. + */ + unsigned long long FileSize() const; + + /** sets the filesize hash + * + * @param Size of the file + * @return @see #push_back + */ + bool FileSize(unsigned long long const Size); + /** check if the given hash type is supported * * @param type to check @@ -166,7 +182,7 @@ class HashStringList class PrivateHashes; class Hashes { - PrivateHashes *d; + PrivateHashes * const d; public: /* those will disappear in the future as it is hard to add new ones this way. diff --git a/apt-pkg/contrib/hashsum_template.h b/apt-pkg/contrib/hashsum_template.h index 869dc5cb7..d0ea0971e 100644 --- a/apt-pkg/contrib/hashsum_template.h +++ b/apt-pkg/contrib/hashsum_template.h @@ -87,7 +87,7 @@ class HashSumValue Sum[I] = S[I]; } - HashSumValue(std::string Str) + explicit HashSumValue(std::string const &Str) { memset(Sum,0,sizeof(Sum)); Set(Str); diff --git a/apt-pkg/contrib/macros.h b/apt-pkg/contrib/macros.h index 2f9c6c269..afa385c75 100644 --- a/apt-pkg/contrib/macros.h +++ b/apt-pkg/contrib/macros.h @@ -148,13 +148,19 @@ #define APT_IGNORE_DEPRECATED(XXX) XXX #endif +#if __cplusplus >= 201103L + #define APT_OVERRIDE override +#else + #define APT_OVERRIDE /* no c++11 standard */ +#endif + // These lines are extracted by the makefiles and the buildsystem // Increasing MAJOR or MINOR results in the need of recompiling all // reverse-dependencies of libapt-pkg against the new SONAME. // Non-ABI-Breaks should only increase RELEASE number. // See also buildlib/libversion.mak -#define APT_PKG_MAJOR 4 -#define APT_PKG_MINOR 15 +#define APT_PKG_MAJOR 5 +#define APT_PKG_MINOR 0 #define APT_PKG_RELEASE 0 #define APT_PKG_ABI ((APT_PKG_MAJOR * 100) + APT_PKG_MINOR) diff --git a/apt-pkg/contrib/md5.h b/apt-pkg/contrib/md5.h index f4992c223..a16ea4d2d 100644 --- a/apt-pkg/contrib/md5.h +++ b/apt-pkg/contrib/md5.h @@ -48,7 +48,7 @@ class MD5Summation : public SummationImplementation public: - bool Add(const unsigned char *inbuf, unsigned long long inlen); + bool Add(const unsigned char *inbuf, unsigned long long inlen) APT_OVERRIDE; using SummationImplementation::Add; MD5SumValue Result(); diff --git a/apt-pkg/contrib/progress.h b/apt-pkg/contrib/progress.h index f7fbc9ccf..427b1bd35 100644 --- a/apt-pkg/contrib/progress.h +++ b/apt-pkg/contrib/progress.h @@ -24,6 +24,7 @@ #include <string> #include <sys/time.h> +#include <apt-pkg/macros.h> #ifndef APT_8_CLEANER_HEADERS using std::string; @@ -74,12 +75,12 @@ class OpTextProgress : public OpProgress bool NoUpdate; bool NoDisplay; unsigned long LastLen; - virtual void Update(); + virtual void Update() APT_OVERRIDE; void Write(const char *S); public: - virtual void Done(); + virtual void Done() APT_OVERRIDE; OpTextProgress(bool NoUpdate = false) : NoUpdate(NoUpdate), NoDisplay(false), LastLen(0) {}; diff --git a/apt-pkg/contrib/sha1.h b/apt-pkg/contrib/sha1.h index 5770c315a..1c5cb5aa1 100644 --- a/apt-pkg/contrib/sha1.h +++ b/apt-pkg/contrib/sha1.h @@ -37,7 +37,7 @@ class SHA1Summation : public SummationImplementation bool Done; public: - bool Add(const unsigned char *inbuf, unsigned long long inlen); + bool Add(const unsigned char *inbuf, unsigned long long inlen) APT_OVERRIDE; using SummationImplementation::Add; SHA1SumValue Result(); diff --git a/apt-pkg/contrib/sha2.h b/apt-pkg/contrib/sha2.h index a25ad4d32..8b4bdd439 100644 --- a/apt-pkg/contrib/sha2.h +++ b/apt-pkg/contrib/sha2.h @@ -34,7 +34,7 @@ class SHA2SummationBase : public SummationImplementation protected: bool Done; public: - bool Add(const unsigned char *inbuf, unsigned long long len) = 0; + bool Add(const unsigned char *inbuf, unsigned long long len) APT_OVERRIDE = 0; void Result(); }; @@ -45,7 +45,7 @@ class SHA256Summation : public SHA2SummationBase unsigned char Sum[32]; public: - bool Add(const unsigned char *inbuf, unsigned long long len) + bool Add(const unsigned char *inbuf, unsigned long long len) APT_OVERRIDE { if (Done) return false; @@ -78,7 +78,7 @@ class SHA512Summation : public SHA2SummationBase unsigned char Sum[64]; public: - bool Add(const unsigned char *inbuf, unsigned long long len) + bool Add(const unsigned char *inbuf, unsigned long long len) APT_OVERRIDE { if (Done) return false; diff --git a/apt-pkg/contrib/sptr.h b/apt-pkg/contrib/sptr.h index 9df0e44a7..92f4cdec8 100644 --- a/apt-pkg/contrib/sptr.h +++ b/apt-pkg/contrib/sptr.h @@ -22,7 +22,7 @@ #define SMART_POINTER_H template <class T> -class SPtr +class APT_DEPRECATED SPtr { public: T *Ptr; @@ -43,7 +43,7 @@ class SPtr }; template <class T> -class SPtrArray +class APT_DEPRECATED SPtrArray { public: T *Ptr; @@ -60,7 +60,15 @@ class SPtrArray inline SPtrArray(T *Ptr) : Ptr(Ptr) {}; inline SPtrArray() : Ptr(0) {}; +#if __GNUC__ >= 4 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations" + // gcc warns about this, but we can do nothing here… +#endif inline ~SPtrArray() {delete [] Ptr;}; +#if __GNUC__ >= 4 + #pragma GCC diagnostic pop +#endif }; #endif diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index 0db4c57b2..05624f7fb 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -1308,7 +1308,7 @@ void ioprintf(ostream &out,const char *format,...) va_list args; ssize_t size = 400; while (true) { - bool ret = false; + bool ret; va_start(args,format); ret = iovprintf(out, format, args, size); va_end(args); @@ -1322,7 +1322,7 @@ void strprintf(string &out,const char *format,...) ssize_t size = 400; std::ostringstream outstr; while (true) { - bool ret = false; + bool ret; va_start(args,format); ret = iovprintf(outstr, format, args, size); va_end(args); @@ -1637,8 +1637,6 @@ URI::operator string() } /*}}}*/ // URI::SiteOnly - Return the schema and site for the URI /*{{{*/ -// --------------------------------------------------------------------- -/* */ string URI::SiteOnly(const string &URI) { ::URI U(URI); @@ -1648,9 +1646,18 @@ string URI::SiteOnly(const string &URI) return U; } /*}}}*/ +// URI::ArchiveOnly - Return the schema, site and cleaned path for the URI /*{{{*/ +string URI::ArchiveOnly(const string &URI) +{ + ::URI U(URI); + U.User.clear(); + U.Password.clear(); + if (U.Path.empty() == false && U.Path[U.Path.length() - 1] == '/') + U.Path.erase(U.Path.length() - 1); + return U; +} + /*}}}*/ // URI::NoUserPassword - Return the schema, site and path for the URI /*{{{*/ -// --------------------------------------------------------------------- -/* */ string URI::NoUserPassword(const string &URI) { ::URI U(URI); diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h index d64270aaf..01bbfef72 100644 --- a/apt-pkg/contrib/strutl.h +++ b/apt-pkg/contrib/strutl.h @@ -167,6 +167,7 @@ class URI inline void operator =(const std::string &From) {CopyFrom(From);} inline bool empty() {return Access.empty();}; static std::string SiteOnly(const std::string &URI); + static std::string ArchiveOnly(const std::string &URI); static std::string NoUserPassword(const std::string &URI); URI(std::string Path) {CopyFrom(Path);} diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index d672b4fd8..c43ee7b91 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -16,56 +16,34 @@ #include <apt-pkg/deblistparser.h> #include <apt-pkg/debrecords.h> #include <apt-pkg/configuration.h> -#include <apt-pkg/progress.h> #include <apt-pkg/error.h> -#include <apt-pkg/strutl.h> -#include <apt-pkg/acquire-item.h> -#include <apt-pkg/debmetaindex.h> -#include <apt-pkg/gpgv.h> #include <apt-pkg/fileutl.h> #include <apt-pkg/indexfile.h> -#include <apt-pkg/mmap.h> #include <apt-pkg/pkgcache.h> #include <apt-pkg/cacheiterators.h> -#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> -#include <sstream> #include <string> +#include <sstream> + #include <sys/stat.h> /*}}}*/ -using std::string; - -// SourcesIndex::debSourcesIndex - Constructor /*{{{*/ -// --------------------------------------------------------------------- -/* */ -debSourcesIndex::debSourcesIndex(string URI,string Dist,string Section,bool Trusted) : - pkgIndexFile(Trusted), URI(URI), Dist(Dist), Section(Section) +// Sources Index /*{{{*/ +debSourcesIndex::debSourcesIndex(IndexTarget const &Target,bool const Trusted) : + pkgDebianIndexTargetFile(Target, Trusted), d(NULL) { } - /*}}}*/ -// SourcesIndex::SourceInfo - Short 1 liner describing a source /*{{{*/ -// --------------------------------------------------------------------- -/* The result looks like: - http://foo/debian/ stable/main src 1.1.1 (dsc) */ -string debSourcesIndex::SourceInfo(pkgSrcRecords::Parser const &Record, +std::string debSourcesIndex::SourceInfo(pkgSrcRecords::Parser const &Record, pkgSrcRecords::File const &File) const { - string Res; - Res = ::URI::NoUserPassword(URI) + ' '; - if (Dist[Dist.size() - 1] == '/') - { - if (Dist != "/") - Res += Dist; - } - else - Res += Dist + '/' + Section; - + // The result looks like: http://foo/debian/ stable/main src 1.1.1 (dsc) + std::string Res = Target.Description; + Res.erase(Target.Description.rfind(' ')); + Res += " "; Res += Record.Package(); Res += " "; @@ -74,622 +52,111 @@ string debSourcesIndex::SourceInfo(pkgSrcRecords::Parser const &Record, Res += " (" + File.Type + ")"; return Res; } - /*}}}*/ -// SourcesIndex::CreateSrcParser - Get a parser for the source files /*{{{*/ -// --------------------------------------------------------------------- -/* */ pkgSrcRecords::Parser *debSourcesIndex::CreateSrcParser() const { - string SourcesURI = _config->FindDir("Dir::State::lists") + - URItoFileName(IndexURI("Sources")); - - 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); - } + std::string const SourcesURI = IndexFileName(); if (FileExists(SourcesURI)) return new debSrcRecordParser(SourcesURI, this); return NULL; } - /*}}}*/ -// SourcesIndex::Describe - Give a descriptive path to the index /*{{{*/ -// --------------------------------------------------------------------- -/* */ -string debSourcesIndex::Describe(bool Short) const -{ - char S[300]; - if (Short == true) - snprintf(S,sizeof(S),"%s",Info("Sources").c_str()); - else - snprintf(S,sizeof(S),"%s (%s)",Info("Sources").c_str(), - IndexFile("Sources").c_str()); - - return S; -} - /*}}}*/ -// SourcesIndex::Info - One liner describing the index URI /*{{{*/ -// --------------------------------------------------------------------- -/* */ -string debSourcesIndex::Info(const char *Type) const +bool debSourcesIndex::OpenListFile(FileFd &, std::string const &) { - string Info = ::URI::NoUserPassword(URI) + ' '; - if (Dist[Dist.size() - 1] == '/') - { - if (Dist != "/") - Info += Dist; - } - else - Info += Dist + '/' + Section; - Info += " "; - Info += Type; - return Info; + return true; } - /*}}}*/ -// SourcesIndex::Index* - Return the URI to the index files /*{{{*/ -// --------------------------------------------------------------------- -/* */ -string debSourcesIndex::IndexFile(const char *Type) const +pkgCacheListParser * debSourcesIndex::CreateListParser(FileFd &) { - string s = URItoFileName(IndexURI(Type)); - - 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; + return NULL; } - -string debSourcesIndex::IndexURI(const char *Type) const +uint8_t debSourcesIndex::GetIndexFlags() const { - string Res; - if (Dist[Dist.size() - 1] == '/') - { - if (Dist != "/") - Res = URI + Dist; - else - Res = URI; - } - else - Res = URI + "dists/" + Dist + '/' + Section + - "/source/"; - - Res += Type; - return Res; + return 0; } /*}}}*/ -// SourcesIndex::Exists - Check if the index is available /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool debSourcesIndex::Exists() const +// Packages Index /*{{{*/ +debPackagesIndex::debPackagesIndex(IndexTarget const &Target, bool const Trusted) : + pkgDebianIndexTargetFile(Target, Trusted), d(NULL) { - return FileExists(IndexFile("Sources")); } - /*}}}*/ -// SourcesIndex::Size - Return the size of the index /*{{{*/ -// --------------------------------------------------------------------- -/* */ -unsigned long debSourcesIndex::Size() const +std::string debPackagesIndex::ArchiveInfo(pkgCache::VerIterator const &Ver) const { - unsigned long size = 0; - - /* we need to ignore errors here; if the lists are absent, just return 0 */ - _error->PushToStack(); - - FileFd f(IndexFile("Sources"), FileFd::ReadOnly, FileFd::Extension); - if (!f.Failed()) - size = f.Size(); + std::string Res = Target.Description; + Res.erase(Target.Description.rfind(' ')); - if (_error->PendingError() == true) - size = 0; - _error->RevertToStack(); - - return size; -} - /*}}}*/ - -// PackagesIndex::debPackagesIndex - Contructor /*{{{*/ -// --------------------------------------------------------------------- -/* */ -debPackagesIndex::debPackagesIndex(string const &URI, string const &Dist, string const &Section, - bool const &Trusted, string const &Arch) : - pkgIndexFile(Trusted), URI(URI), Dist(Dist), Section(Section), Architecture(Arch) -{ - if (Architecture == "native") - Architecture = _config->Find("APT::Architecture"); -} - /*}}}*/ -// PackagesIndex::ArchiveInfo - Short version of the archive url /*{{{*/ -// --------------------------------------------------------------------- -/* This is a shorter version that is designed to be < 60 chars or so */ -string debPackagesIndex::ArchiveInfo(pkgCache::VerIterator Ver) const -{ - string Res = ::URI::NoUserPassword(URI) + ' '; - if (Dist[Dist.size() - 1] == '/') - { - if (Dist != "/") - Res += Dist; - } - else - Res += Dist + '/' + Section; - Res += " "; Res += Ver.ParentPkg().Name(); Res += " "; - if (Dist[Dist.size() - 1] != '/') + std::string const Dist = Target.Option(IndexTarget::RELEASE); + if (Dist.empty() == false && Dist[Dist.size() - 1] != '/') Res.append(Ver.Arch()).append(" "); Res += Ver.VerStr(); return Res; } - /*}}}*/ -// PackagesIndex::Describe - Give a descriptive path to the index /*{{{*/ -// --------------------------------------------------------------------- -/* This should help the user find the index in the sources.list and - in the filesystem for problem solving */ -string debPackagesIndex::Describe(bool Short) const -{ - char S[300]; - if (Short == true) - snprintf(S,sizeof(S),"%s",Info("Packages").c_str()); - else - snprintf(S,sizeof(S),"%s (%s)",Info("Packages").c_str(), - IndexFile("Packages").c_str()); - return S; -} - /*}}}*/ -// PackagesIndex::Info - One liner describing the index URI /*{{{*/ -// --------------------------------------------------------------------- -/* */ -string debPackagesIndex::Info(const char *Type) const +uint8_t debPackagesIndex::GetIndexFlags() const { - string Info = ::URI::NoUserPassword(URI) + ' '; - if (Dist[Dist.size() - 1] == '/') - { - if (Dist != "/") - Info += Dist; - } - else - Info += Dist + '/' + Section; - Info += " "; - if (Dist[Dist.size() - 1] != '/') - Info += Architecture + " "; - Info += Type; - return Info; -} - /*}}}*/ -// PackagesIndex::Index* - Return the URI to the index files /*{{{*/ -// --------------------------------------------------------------------- -/* */ -string debPackagesIndex::IndexFile(const char *Type) const -{ - string s =_config->FindDir("Dir::State::lists") + URItoFileName(IndexURI(Type)); - - 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 -{ - string Res; - if (Dist[Dist.size() - 1] == '/') - { - if (Dist != "/") - Res = URI + Dist; - else - Res = URI; - } - else - Res = URI + "dists/" + Dist + '/' + Section + - "/binary-" + Architecture + '/'; - - Res += Type; - return Res; -} - /*}}}*/ -// PackagesIndex::Exists - Check if the index is available /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool debPackagesIndex::Exists() const -{ - return FileExists(IndexFile("Packages")); -} - /*}}}*/ -// PackagesIndex::Size - Return the size of the index /*{{{*/ -// --------------------------------------------------------------------- -/* This is really only used for progress reporting. */ -unsigned long debPackagesIndex::Size() const -{ - unsigned long size = 0; - - /* we need to ignore errors here; if the lists are absent, just return 0 */ - _error->PushToStack(); - - FileFd f(IndexFile("Packages"), FileFd::ReadOnly, FileFd::Extension); - if (!f.Failed()) - size = f.Size(); - - if (_error->PendingError() == true) - size = 0; - _error->RevertToStack(); - - return size; -} - /*}}}*/ -// PackagesIndex::Merge - Load the index file into a cache /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const -{ - string PackageFile = IndexFile("Packages"); - FileFd Pkg(PackageFile,FileFd::ReadOnly, FileFd::Extension); - debListParser Parser(&Pkg, Architecture); - - if (_error->PendingError() == true) - return _error->Error("Problem opening %s",PackageFile.c_str()); - if (Prog != NULL) - Prog->SubProgress(0,Info("Packages")); - ::URI Tmp(URI); - if (Gen.SelectFile(PackageFile,Tmp.Host,*this) == false) - return _error->Error("Problem with SelectFile %s",PackageFile.c_str()); - - // Store the IMS information - pkgCache::PkgFileIterator File = Gen.GetCurFile(); - pkgCacheGenerator::Dynamic<pkgCache::PkgFileIterator> DynFile(File); - File->Size = Pkg.FileSize(); - File->mtime = Pkg.ModificationTime(); - - if (Gen.MergeList(Parser) == false) - return _error->Error("Problem with MergeList %s",PackageFile.c_str()); - - // Check the release file - string ReleaseFile = debReleaseIndex(URI,Dist).MetaIndexFile("InRelease"); - bool releaseExists = false; - if (FileExists(ReleaseFile) == true) - releaseExists = true; - else - ReleaseFile = debReleaseIndex(URI,Dist).MetaIndexFile("Release"); - - if (releaseExists == true || FileExists(ReleaseFile) == true) - { - FileFd Rel; - // Beware: The 'Release' file might be clearsigned in case the - // signature for an 'InRelease' file couldn't be checked - if (OpenMaybeClearSignedFile(ReleaseFile, Rel) == false) - return false; - - if (_error->PendingError() == true) - return false; - Parser.LoadReleaseInfo(File,Rel,Section); - } - - return true; -} - /*}}}*/ -// PackagesIndex::FindInCache - Find this index /*{{{*/ -// --------------------------------------------------------------------- -/* */ -pkgCache::PkgFileIterator debPackagesIndex::FindInCache(pkgCache &Cache) const -{ - string FileName = IndexFile("Packages"); - pkgCache::PkgFileIterator File = Cache.FileBegin(); - for (; File.end() == false; ++File) - { - if (File.FileName() == NULL || FileName != File.FileName()) - continue; - - struct stat St; - if (stat(File.FileName(),&St) != 0) - { - if (_config->FindB("Debug::pkgCacheGen", false)) - std::clog << "PackagesIndex::FindInCache - stat failed on " << File.FileName() << std::endl; - return pkgCache::PkgFileIterator(Cache); - } - if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime) - { - if (_config->FindB("Debug::pkgCacheGen", false)) - std::clog << "PackagesIndex::FindInCache - size (" << St.st_size << " <> " << File->Size - << ") or mtime (" << St.st_mtime << " <> " << File->mtime - << ") doesn't match for " << File.FileName() << std::endl; - return pkgCache::PkgFileIterator(Cache); - } - return File; - } - - return File; + return 0; } /*}}}*/ - -// TranslationsIndex::debTranslationsIndex - Contructor /*{{{*/ -// --------------------------------------------------------------------- -/* */ -debTranslationsIndex::debTranslationsIndex(std::string const &URI, std::string const &Dist, - std::string const &Section, std::string const &Translation) : - pkgIndexFile(true), URI(URI), Dist(Dist), Section(Section), - Language(Translation) +// Translation-* Index /*{{{*/ +debTranslationsIndex::debTranslationsIndex(IndexTarget const &Target) : + pkgDebianIndexTargetFile(Target, true), d(NULL) {} - /*}}}*/ -// TranslationIndex::Trans* - Return the URI to the translation files /*{{{*/ -// --------------------------------------------------------------------- -/* */ -string debTranslationsIndex::IndexFile(const char *Type) const +bool debTranslationsIndex::HasPackages() const { - string s =_config->FindDir("Dir::State::lists") + URItoFileName(IndexURI(Type)); - - 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; + return Exists(); } -string debTranslationsIndex::IndexURI(const char *Type) const +bool debTranslationsIndex::OpenListFile(FileFd &Pkg, std::string const &FileName) { - string Res; - if (Dist[Dist.size() - 1] == '/') - { - if (Dist != "/") - Res = URI + Dist; - else - Res = URI; - } - else - Res = URI + "dists/" + Dist + '/' + Section + - "/i18n/Translation-"; - - Res += Type; - return Res; -} - /*}}}*/ -// TranslationsIndex::Describe - Give a descriptive path to the index /*{{{*/ -// --------------------------------------------------------------------- -/* This should help the user find the index in the sources.list and - in the filesystem for problem solving */ -string debTranslationsIndex::Describe(bool Short) const -{ - std::string S; - if (Short == true) - strprintf(S,"%s",Info(TranslationFile().c_str()).c_str()); - else - strprintf(S,"%s (%s)",Info(TranslationFile().c_str()).c_str(), - IndexFile(Language.c_str()).c_str()); - return S; -} - /*}}}*/ -// TranslationsIndex::Info - One liner describing the index URI /*{{{*/ -// --------------------------------------------------------------------- -/* */ -string debTranslationsIndex::Info(const char *Type) const -{ - string Info = ::URI::NoUserPassword(URI) + ' '; - if (Dist[Dist.size() - 1] == '/') - { - if (Dist != "/") - Info += Dist; - } - else - Info += Dist + '/' + Section; - Info += " "; - Info += Type; - return Info; + if (FileExists(FileName)) + return pkgDebianIndexTargetFile::OpenListFile(Pkg, FileName); + return true; } - /*}}}*/ -bool debTranslationsIndex::HasPackages() const /*{{{*/ +uint8_t debTranslationsIndex::GetIndexFlags() const { - return FileExists(IndexFile(Language.c_str())); + return pkgCache::Flag::NotSource | pkgCache::Flag::NoPackages; } - /*}}}*/ -// TranslationsIndex::Exists - Check if the index is available /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool debTranslationsIndex::Exists() const +std::string debTranslationsIndex::GetArchitecture() const { - return FileExists(IndexFile(Language.c_str())); + return std::string(); } - /*}}}*/ -// TranslationsIndex::Size - Return the size of the index /*{{{*/ -// --------------------------------------------------------------------- -/* This is really only used for progress reporting. */ -unsigned long debTranslationsIndex::Size() const +pkgCacheListParser * debTranslationsIndex::CreateListParser(FileFd &Pkg) { - unsigned long size = 0; - - /* we need to ignore errors here; if the lists are absent, just return 0 */ + if (Pkg.IsOpen() == false) + return NULL; _error->PushToStack(); - - FileFd f(IndexFile(Language.c_str()), FileFd::ReadOnly, FileFd::Extension); - if (!f.Failed()) - size = f.Size(); - - if (_error->PendingError() == true) - size = 0; - _error->RevertToStack(); - - return size; + pkgCacheListParser * const Parser = new debTranslationsParser(&Pkg); + bool const newError = _error->PendingError(); + _error->MergeWithStack(); + return newError ? NULL : Parser; } /*}}}*/ -// TranslationsIndex::Merge - Load the index file into a cache /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const -{ - // Check the translation file, if in use - string TranslationFile = IndexFile(Language.c_str()); - if (FileExists(TranslationFile)) - { - FileFd Trans(TranslationFile,FileFd::ReadOnly, FileFd::Extension); - debTranslationsParser TransParser(&Trans); - if (_error->PendingError() == true) - return false; - - if (Prog != NULL) - Prog->SubProgress(0, Info(TranslationFile.c_str())); - if (Gen.SelectFile(TranslationFile,string(),*this) == false) - return _error->Error("Problem with SelectFile %s",TranslationFile.c_str()); - - // Store the IMS information - pkgCache::PkgFileIterator TransFile = Gen.GetCurFile(); - TransFile->Size = Trans.FileSize(); - TransFile->mtime = Trans.ModificationTime(); - - if (Gen.MergeList(TransParser) == false) - return _error->Error("Problem with MergeList %s",TranslationFile.c_str()); - } - - return true; -} - /*}}}*/ -// TranslationsIndex::FindInCache - Find this index /*{{{*/ -// --------------------------------------------------------------------- -/* */ -pkgCache::PkgFileIterator debTranslationsIndex::FindInCache(pkgCache &Cache) const +// dpkg/status Index /*{{{*/ +debStatusIndex::debStatusIndex(std::string const &File) : pkgDebianIndexRealFile(File, true), d(NULL) { - string FileName = IndexFile(Language.c_str()); - - pkgCache::PkgFileIterator File = Cache.FileBegin(); - for (; File.end() == false; ++File) - { - if (FileName != File.FileName()) - continue; - - struct stat St; - if (stat(File.FileName(),&St) != 0) - { - if (_config->FindB("Debug::pkgCacheGen", false)) - std::clog << "TranslationIndex::FindInCache - stat failed on " << File.FileName() << std::endl; - return pkgCache::PkgFileIterator(Cache); - } - if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime) - { - if (_config->FindB("Debug::pkgCacheGen", false)) - std::clog << "TranslationIndex::FindInCache - size (" << St.st_size << " <> " << File->Size - << ") or mtime (" << St.st_mtime << " <> " << File->mtime - << ") doesn't match for " << File.FileName() << std::endl; - return pkgCache::PkgFileIterator(Cache); - } - return File; - } - return File; } - /*}}}*/ -// StatusIndex::debStatusIndex - Constructor /*{{{*/ -// --------------------------------------------------------------------- -/* */ -debStatusIndex::debStatusIndex(string File) : pkgIndexFile(true), File(File) +std::string debStatusIndex::GetArchitecture() const { + return std::string(); } - /*}}}*/ -// StatusIndex::Size - Return the size of the index /*{{{*/ -// --------------------------------------------------------------------- -/* */ -unsigned long debStatusIndex::Size() const -{ - struct stat S; - if (stat(File.c_str(),&S) != 0) - return 0; - return S.st_size; -} - /*}}}*/ -// StatusIndex::Merge - Load the index file into a cache /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool debStatusIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const -{ - FileFd Pkg(File,FileFd::ReadOnly, FileFd::Extension); - if (_error->PendingError() == true) - return false; - debListParser Parser(&Pkg); - if (_error->PendingError() == true) - return false; - - if (Prog != NULL) - Prog->SubProgress(0,File); - if (Gen.SelectFile(File,string(),*this,pkgCache::Flag::NotSource) == false) - return _error->Error("Problem with SelectFile %s",File.c_str()); - - // Store the IMS information - pkgCache::PkgFileIterator CFile = Gen.GetCurFile(); - CFile->Size = Pkg.FileSize(); - CFile->mtime = Pkg.ModificationTime(); - map_stringitem_t const storage = Gen.StoreString(pkgCacheGenerator::MIXED, "now"); - CFile->Archive = storage; - - if (Gen.MergeList(Parser) == false) - return _error->Error("Problem with MergeList %s",File.c_str()); - return true; -} - /*}}}*/ -// StatusIndex::FindInCache - Find this index /*{{{*/ -// --------------------------------------------------------------------- -/* */ -pkgCache::PkgFileIterator debStatusIndex::FindInCache(pkgCache &Cache) const +std::string debStatusIndex::GetComponent() const { - pkgCache::PkgFileIterator File = Cache.FileBegin(); - for (; File.end() == false; ++File) - { - if (this->File != File.FileName()) - continue; - - struct stat St; - if (stat(File.FileName(),&St) != 0) - { - if (_config->FindB("Debug::pkgCacheGen", false)) - std::clog << "StatusIndex::FindInCache - stat failed on " << File.FileName() << std::endl; - return pkgCache::PkgFileIterator(Cache); - } - if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime) - { - if (_config->FindB("Debug::pkgCacheGen", false)) - std::clog << "StatusIndex::FindInCache - size (" << St.st_size << " <> " << File->Size - << ") or mtime (" << St.st_mtime << " <> " << File->mtime - << ") doesn't match for " << File.FileName() << std::endl; - return pkgCache::PkgFileIterator(Cache); - } - return File; - } - return File; + return "now"; } - /*}}}*/ -// StatusIndex::Exists - Check if the index is available /*{{{*/ -// --------------------------------------------------------------------- -/* */ -APT_CONST bool debStatusIndex::Exists() const +uint8_t debStatusIndex::GetIndexFlags() const { - // Abort if the file does not exist. - return true; + return pkgCache::Flag::NotSource; } /*}}}*/ - -// 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 +// DebPkgFile Index - a single .deb file as an index /*{{{*/ +debDebPkgFileIndex::debDebPkgFileIndex(std::string const &DebFile) + : pkgDebianIndexRealFile(DebFile, true), d(NULL), DebFile(DebFile) { - return FileExists(DebFile); } bool debDebPkgFileIndex::GetContent(std::ostream &content, std::string const &debfile) { + struct stat Buf; + if (stat(debfile.c_str(), &Buf) != 0) + return false; + // get the control data out of the deb file via dpkg-deb -I std::string dpkg = _config->Find("Dir::Bin::dpkg","dpkg-deb"); std::vector<const char *> Args; @@ -716,106 +183,86 @@ bool debDebPkgFileIndex::GetContent(std::ostream &content, std::string const &de ExecWait(Child, "Popen"); content << "Filename: " << debfile << "\n"; - struct stat Buf; - if (stat(debfile.c_str(), &Buf) != 0) - return false; content << "Size: " << Buf.st_size << "\n"; return true; } -bool debDebPkgFileIndex::Merge(pkgCacheGenerator& Gen, OpProgress* Prog) const +bool debDebPkgFileIndex::OpenListFile(FileFd &Pkg, std::string const &FileName) { - if(Prog) - Prog->SubProgress(0, "Reading deb file"); - // write the control data to a tempfile - SPtr<FileFd> DebControl = GetTempFile("deb-file-" + flNotDir(DebFile)); - if(DebControl == NULL) + if (GetTempFile("deb-file-" + flNotDir(FileName), true, &Pkg) == NULL) return false; std::ostringstream content; - if (GetContent(content, DebFile) == false) + if (GetContent(content, FileName) == false) return false; std::string const contentstr = content.str(); - DebControl->Write(contentstr.c_str(), contentstr.length()); - // 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()); - + if (contentstr.empty()) + return true; + if (Pkg.Write(contentstr.c_str(), contentstr.length()) == false || Pkg.Seek(0) == false) + return false; return true; } +pkgCacheListParser * debDebPkgFileIndex::CreateListParser(FileFd &Pkg) +{ + if (Pkg.IsOpen() == false) + return NULL; + _error->PushToStack(); + pkgCacheListParser * const Parser = new debDebFileParser(&Pkg, DebFile); + bool const newError = _error->PendingError(); + _error->MergeWithStack(); + return newError ? NULL : Parser; +} +uint8_t debDebPkgFileIndex::GetIndexFlags() const +{ + return pkgCache::Flag::LocalSource; +} +std::string debDebPkgFileIndex::GetArchitecture() const +{ + return std::string(); +} +std::string debDebPkgFileIndex::GetComponent() const +{ + return "local-deb"; +} pkgCache::PkgFileIterator debDebPkgFileIndex::FindInCache(pkgCache &Cache) const { + std::string const FileName = IndexFileName(); pkgCache::PkgFileIterator File = Cache.FileBegin(); for (; File.end() == false; ++File) { - if (File.FileName() == NULL || DebFile != File.FileName()) + if (File.FileName() == NULL || FileName != File.FileName()) continue; - - return File; + // we can't do size checks here as file size != content size + 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); + return File; } -unsigned long debDscFileIndex::Size() const + /*}}}*/ +// DscFile Index - a single .dsc file as an index /*{{{*/ +debDscFileIndex::debDscFileIndex(std::string const &DscFile) + : pkgDebianIndexRealFile(DscFile, true), d(NULL) { - 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)) + if (Exists() == false) return NULL; - - return new debDscRecordParser(DscFile,this); + return new debDscRecordParser(File, this); } /*}}}*/ + // Index File types for Debian /*{{{*/ class APT_HIDDEN debIFTypeSrc : public pkgIndexFile::Type { public: - debIFTypeSrc() {Label = "Debian Source Index";}; }; class APT_HIDDEN debIFTypePkg : public pkgIndexFile::Type { public: - - virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const + virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator const &File) const APT_OVERRIDE { return new debRecordParser(File.FileName(),*File.Cache()); }; @@ -829,8 +276,7 @@ class APT_HIDDEN debIFTypeTrans : public debIFTypePkg class APT_HIDDEN debIFTypeStatus : public pkgIndexFile::Type { public: - - virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const + virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator const &File) const APT_OVERRIDE { return new debRecordParser(File.FileName(),*File.Cache()); }; @@ -839,29 +285,29 @@ class APT_HIDDEN debIFTypeStatus : public pkgIndexFile::Type class APT_HIDDEN debIFTypeDebPkgFile : public pkgIndexFile::Type { public: - virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const + virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator const &File) const APT_OVERRIDE { return new debDebFileRecordParser(File.FileName()); }; - debIFTypeDebPkgFile() {Label = "deb Package file";}; + debIFTypeDebPkgFile() {Label = "Debian deb file";}; }; class APT_HIDDEN debIFTypeDscFile : public pkgIndexFile::Type { public: - virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string DscFile) const + virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string const &DscFile) const APT_OVERRIDE { return new debDscRecordParser(DscFile, NULL); }; - debIFTypeDscFile() {Label = "dsc File Source Index";}; + debIFTypeDscFile() {Label = "Debian dsc file";}; }; class APT_HIDDEN debIFTypeDebianSourceDir : public pkgIndexFile::Type { public: - virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string SourceDir) const + virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string const &SourceDir) const APT_OVERRIDE { - return new debDscRecordParser(SourceDir + string("/debian/control"), NULL); + return new debDscRecordParser(SourceDir + std::string("/debian/control"), NULL); }; - debIFTypeDebianSourceDir() {Label = "debian/control File Source Index";}; + debIFTypeDebianSourceDir() {Label = "Debian control file";}; }; APT_HIDDEN debIFTypeSrc _apt_Src; @@ -909,3 +355,4 @@ debTranslationsIndex::~debTranslationsIndex() {} debSourcesIndex::~debSourcesIndex() {} debDebPkgFileIndex::~debDebPkgFileIndex() {} +debDscFileIndex::~debDscFileIndex() {} diff --git a/apt-pkg/deb/debindexfile.h b/apt-pkg/deb/debindexfile.h index 1e5882071..dc75a01ab 100644 --- a/apt-pkg/deb/debindexfile.h +++ b/apt-pkg/deb/debindexfile.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: debindexfile.h,v 1.3.2.1 2003/12/24 23:09:17 mdz Exp $ /* ###################################################################### Debian Index Files @@ -27,155 +26,105 @@ class OpProgress; class pkgAcquire; class pkgCacheGenerator; - -class APT_HIDDEN debStatusIndex : public pkgIndexFile +class debStatusIndex : public pkgDebianIndexRealFile { - /** \brief dpointer placeholder (for later in case we need it) */ - void *d; + void * const d; +protected: + virtual std::string GetArchitecture() const APT_OVERRIDE; + virtual std::string GetComponent() const APT_OVERRIDE; + virtual uint8_t GetIndexFlags() const APT_OVERRIDE; - protected: - std::string File; +public: - public: + virtual const Type *GetType() const APT_OVERRIDE APT_CONST; - virtual const Type *GetType() const APT_CONST; - - // Interface for acquire - virtual std::string Describe(bool /*Short*/) const {return File;}; - // Interface for the Cache Generator - virtual bool Exists() const; - virtual bool HasPackages() const {return true;}; - virtual unsigned long Size() const; - virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const; - bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog, unsigned long const Flag) const; - virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const; - - debStatusIndex(std::string File); + virtual bool HasPackages() const APT_OVERRIDE {return true;}; + // Abort if the file does not exist. + virtual bool Exists() const APT_OVERRIDE {return true;}; + + debStatusIndex(std::string const &File); virtual ~debStatusIndex(); }; - -class APT_HIDDEN debPackagesIndex : public pkgIndexFile -{ - /** \brief dpointer placeholder (for later in case we need it) */ - void *d; - - std::string URI; - std::string Dist; - std::string Section; - std::string Architecture; - APT_HIDDEN std::string Info(const char *Type) const; - APT_HIDDEN std::string IndexFile(const char *Type) const; - APT_HIDDEN std::string IndexURI(const char *Type) const; +class debPackagesIndex : public pkgDebianIndexTargetFile +{ + void * const d; +protected: + virtual uint8_t GetIndexFlags() const APT_OVERRIDE; - public: - - virtual const Type *GetType() const APT_CONST; +public: + virtual const Type *GetType() const APT_OVERRIDE APT_CONST; // Stuff for accessing files on remote items - virtual std::string ArchiveInfo(pkgCache::VerIterator Ver) const; - virtual std::string ArchiveURI(std::string File) const {return URI + File;}; - - // Interface for acquire - virtual std::string Describe(bool Short) const; - + virtual std::string ArchiveInfo(pkgCache::VerIterator const &Ver) const APT_OVERRIDE; + // Interface for the Cache Generator - virtual bool Exists() const; - virtual bool HasPackages() const {return true;}; - virtual unsigned long Size() const; - virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const; - virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const; - - debPackagesIndex(std::string const &URI, std::string const &Dist, std::string const &Section, - bool const &Trusted, std::string const &Arch = "native"); + virtual bool HasPackages() const APT_OVERRIDE {return true;}; + + debPackagesIndex(IndexTarget const &Target, bool const Trusted); virtual ~debPackagesIndex(); }; -class APT_HIDDEN debTranslationsIndex : public pkgIndexFile +class debTranslationsIndex : public pkgDebianIndexTargetFile { - /** \brief dpointer placeholder (for later in case we need it) */ - void *d; + void * const d; +protected: + virtual std::string GetArchitecture() const APT_OVERRIDE; + virtual uint8_t GetIndexFlags() const APT_OVERRIDE; + virtual bool OpenListFile(FileFd &Pkg, std::string const &FileName) APT_OVERRIDE; + APT_HIDDEN virtual pkgCacheListParser * CreateListParser(FileFd &Pkg) APT_OVERRIDE; - std::string const URI; - std::string const Dist; - std::string const Section; - std::string const Language; +public: - APT_HIDDEN std::string Info(const char *Type) const; - APT_HIDDEN std::string IndexFile(const char *Type) const; - APT_HIDDEN std::string IndexURI(const char *Type) const; - - APT_HIDDEN std::string TranslationFile() const {return std::string("Translation-").append(Language);}; - - public: - - virtual const Type *GetType() const APT_CONST; - - // Interface for acquire - virtual std::string Describe(bool Short) const; + virtual const Type *GetType() const APT_OVERRIDE APT_CONST; // Interface for the Cache Generator - virtual bool Exists() const; - virtual bool HasPackages() const; - virtual unsigned long Size() const; - virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const; - virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const; + virtual bool HasPackages() const APT_OVERRIDE; - debTranslationsIndex(std::string const &URI,std::string const &Dist,std::string const &Section, std::string const &Language); + debTranslationsIndex(IndexTarget const &Target); virtual ~debTranslationsIndex(); }; -class APT_HIDDEN debSourcesIndex : public pkgIndexFile +class debSourcesIndex : public pkgDebianIndexTargetFile { - /** \brief dpointer placeholder (for later in case we need it) */ - void *d; - - std::string URI; - std::string Dist; - std::string Section; - - APT_HIDDEN std::string Info(const char *Type) const; - APT_HIDDEN std::string IndexFile(const char *Type) const; - APT_HIDDEN std::string IndexURI(const char *Type) const; + void * const d; + virtual uint8_t GetIndexFlags() const APT_OVERRIDE; + virtual bool OpenListFile(FileFd &Pkg, std::string const &FileName) APT_OVERRIDE; + APT_HIDDEN virtual pkgCacheListParser * CreateListParser(FileFd &Pkg) APT_OVERRIDE; public: - virtual const Type *GetType() const APT_CONST; + virtual const Type *GetType() const APT_OVERRIDE APT_CONST; // Stuff for accessing files on remote items virtual std::string SourceInfo(pkgSrcRecords::Parser const &Record, - pkgSrcRecords::File const &File) const; - virtual std::string ArchiveURI(std::string File) const {return URI + File;}; - - // Interface for acquire - virtual std::string Describe(bool Short) const; + pkgSrcRecords::File const &File) const APT_OVERRIDE; // Interface for the record parsers - virtual pkgSrcRecords::Parser *CreateSrcParser() const; - + virtual pkgSrcRecords::Parser *CreateSrcParser() const APT_OVERRIDE; + // Interface for the Cache Generator - virtual bool Exists() const; - virtual bool HasPackages() const {return false;}; - virtual unsigned long Size() const; - - debSourcesIndex(std::string URI,std::string Dist,std::string Section,bool Trusted); + virtual bool HasPackages() const APT_OVERRIDE {return false;}; + + debSourcesIndex(IndexTarget const &Target, bool const Trusted); virtual ~debSourcesIndex(); }; -class APT_HIDDEN debDebPkgFileIndex : public pkgIndexFile +class debDebPkgFileIndex : public pkgDebianIndexRealFile { - private: - void *d; + void * const d; std::string DebFile; - std::string DebFileFullPath; - public: - virtual const Type *GetType() const APT_CONST; +protected: + virtual std::string GetComponent() const APT_OVERRIDE; + virtual std::string GetArchitecture() const APT_OVERRIDE; + virtual uint8_t GetIndexFlags() const APT_OVERRIDE; + virtual bool OpenListFile(FileFd &Pkg, std::string const &FileName) APT_OVERRIDE; + APT_HIDDEN virtual pkgCacheListParser * CreateListParser(FileFd &Pkg) APT_OVERRIDE; - virtual std::string Describe(bool /*Short*/) const { - return DebFile; - } +public: + virtual const Type *GetType() const APT_OVERRIDE APT_CONST; /** get the control (file) content of the deb file * @@ -186,43 +135,31 @@ class APT_HIDDEN debDebPkgFileIndex : public pkgIndexFile static bool GetContent(std::ostream &content, std::string const &debfile); // Interface for the Cache Generator - virtual bool Exists() const; - virtual bool HasPackages() const { - return true; - }; - virtual unsigned long Size() const; - virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const; - virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const; + virtual bool HasPackages() const APT_OVERRIDE {return true;} + virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const APT_OVERRIDE; // Interface for acquire - virtual std::string ArchiveURI(std::string /*File*/) const; - debDebPkgFileIndex(std::string DebFile); + debDebPkgFileIndex(std::string const &DebFile); virtual ~debDebPkgFileIndex(); }; -class APT_HIDDEN debDscFileIndex : public pkgIndexFile +class debDscFileIndex : public pkgDebianIndexRealFile { - private: - std::string DscFile; + void * const d; public: - virtual const Type *GetType() const APT_CONST; - virtual pkgSrcRecords::Parser *CreateSrcParser() const; - virtual bool Exists() const; - virtual bool HasPackages() const {return false;}; - virtual unsigned long Size() const; - virtual std::string Describe(bool /*Short*/) const { - return DscFile; - }; - - debDscFileIndex(std::string &DscFile); - virtual ~debDscFileIndex() {}; + virtual const Type *GetType() const APT_OVERRIDE APT_CONST; + virtual pkgSrcRecords::Parser *CreateSrcParser() const APT_OVERRIDE; + virtual bool HasPackages() const APT_OVERRIDE {return false;}; + + debDscFileIndex(std::string const &DscFile); + virtual ~debDscFileIndex(); }; -class APT_HIDDEN debDebianSourceDirIndex : public debDscFileIndex +class debDebianSourceDirIndex : public debDscFileIndex { public: - virtual const Type *GetType() const APT_CONST; + virtual const Type *GetType() const APT_OVERRIDE APT_CONST; }; #endif diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index b80b57bc4..42eca8677 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -18,10 +18,8 @@ #include <apt-pkg/cachefilter.h> #include <apt-pkg/aptconfiguration.h> #include <apt-pkg/strutl.h> -#include <apt-pkg/fileutl.h> #include <apt-pkg/crc-16.h> #include <apt-pkg/md5.h> -#include <apt-pkg/mmap.h> #include <apt-pkg/pkgcache.h> #include <apt-pkg/cacheiterators.h> #include <apt-pkg/tagfile.h> @@ -50,12 +48,9 @@ static debListParser::WordList PrioList[] = { /* Provide an architecture and only this one and "all" will be accepted in Step(), if no Architecture is given we will accept every arch we would accept in general with checkArchitecture() */ -debListParser::debListParser(FileFd *File, string const &Arch) : Tags(File), - Arch(Arch) { - if (Arch == "native") - this->Arch = _config->Find("APT::Architecture"); - Architectures = APT::Configuration::getArchitectures(); - MultiArchEnabled = Architectures.size() > 1; +debListParser::debListParser(FileFd *File) : + pkgCacheListParser(), d(NULL), Tags(File) +{ } /*}}}*/ // ListParser::Package - Return the package name /*{{{*/ @@ -72,7 +67,8 @@ string debListParser::Package() { // --------------------------------------------------------------------- /* This will return the Architecture of the package this section describes */ string debListParser::Architecture() { - return Section.FindS("Architecture"); + std::string const Arch = Section.FindS("Architecture"); + return Arch.empty() ? "none" : Arch; } /*}}}*/ // ListParser::ArchitectureAll /*{{{*/ @@ -97,14 +93,14 @@ unsigned char debListParser::ParseMultiArch(bool const showErrors) /*{{{*/ unsigned char MA; string const MultiArch = Section.FindS("Multi-Arch"); if (MultiArch.empty() == true || MultiArch == "no") - MA = pkgCache::Version::None; + MA = pkgCache::Version::No; else if (MultiArch == "same") { if (ArchitectureAll() == true) { if (showErrors == true) _error->Warning("Architecture: all package '%s' can't be Multi-Arch: same", Section.FindS("Package").c_str()); - MA = pkgCache::Version::None; + MA = pkgCache::Version::No; } else MA = pkgCache::Version::Same; @@ -118,7 +114,7 @@ unsigned char debListParser::ParseMultiArch(bool const showErrors) /*{{{*/ if (showErrors == true) _error->Warning("Unknown Multi-Arch type '%s' for package '%s'", MultiArch.c_str(), Section.FindS("Package").c_str()); - MA = pkgCache::Version::None; + MA = pkgCache::Version::No; } if (ArchitectureAll() == true) @@ -141,7 +137,6 @@ bool debListParser::NewVersion(pkgCache::VerIterator &Ver) map_stringitem_t const idx = StoreString(pkgCacheGenerator::SECTION, Start, Stop - Start); Ver->Section = idx; } -#if APT_PKG_ABI >= 413 // Parse the source package name pkgCache::GrpIterator const G = Ver.ParentPkg().Group(); Ver->SourcePkgName = G->Name; @@ -193,7 +188,6 @@ bool debListParser::NewVersion(pkgCache::VerIterator &Ver) } } } -#endif Ver->MultiArch = ParseMultiArch(true); // Archive Size @@ -209,23 +203,22 @@ bool debListParser::NewVersion(pkgCache::VerIterator &Ver) Ver->Priority = pkgCache::State::Extra; } - if (ParseDepends(Ver,"Depends",pkgCache::Dep::Depends) == false) - return false; if (ParseDepends(Ver,"Pre-Depends",pkgCache::Dep::PreDepends) == false) return false; - if (ParseDepends(Ver,"Suggests",pkgCache::Dep::Suggests) == false) - return false; - if (ParseDepends(Ver,"Recommends",pkgCache::Dep::Recommends) == false) + if (ParseDepends(Ver,"Depends",pkgCache::Dep::Depends) == false) return false; if (ParseDepends(Ver,"Conflicts",pkgCache::Dep::Conflicts) == false) return false; if (ParseDepends(Ver,"Breaks",pkgCache::Dep::DpkgBreaks) == false) return false; + if (ParseDepends(Ver,"Recommends",pkgCache::Dep::Recommends) == false) + return false; + if (ParseDepends(Ver,"Suggests",pkgCache::Dep::Suggests) == false) + return false; if (ParseDepends(Ver,"Replaces",pkgCache::Dep::Replaces) == false) return false; if (ParseDepends(Ver,"Enhances",pkgCache::Dep::Enhances) == false) return false; - // Obsolete. if (ParseDepends(Ver,"Optional",pkgCache::Dep::Suggests) == false) return false; @@ -793,43 +786,23 @@ bool debListParser::ParseDepends(pkgCache::VerIterator &Ver, return _error->Error("Problem parsing dependency %s",Tag); size_t const found = Package.rfind(':'); - // If negative is unspecific it needs to apply on all architectures - if (MultiArchEnabled == true && found == string::npos && - (Type == pkgCache::Dep::Conflicts || - Type == pkgCache::Dep::DpkgBreaks || - Type == pkgCache::Dep::Replaces)) + if (found == string::npos || strcmp(Package.c_str() + found, ":any") == 0) { - for (std::vector<std::string>::const_iterator a = Architectures.begin(); - a != Architectures.end(); ++a) - if (NewDepends(Ver,Package,*a,Version,Op,Type) == false) - return false; - if (NewDepends(Ver,Package,"none",Version,Op,Type) == false) + if (NewDepends(Ver,Package,pkgArch,Version,Op,Type) == false) return false; } - else if (found != string::npos && - strcmp(Package.c_str() + found, ":any") != 0) + else { string Arch = Package.substr(found+1, string::npos); Package = Package.substr(0, found); // Such dependencies are not supposed to be accepted … - // … but this is probably the best thing to do. + // … but this is probably the best thing to do anyway if (Arch == "native") Arch = _config->Find("APT::Architecture"); - if (NewDepends(Ver,Package,Arch,Version,Op,Type) == false) - return false; - } - else - { - if (NewDepends(Ver,Package,pkgArch,Version,Op,Type) == false) - return false; - if ((Type == pkgCache::Dep::Conflicts || - Type == pkgCache::Dep::DpkgBreaks || - Type == pkgCache::Dep::Replaces) && - NewDepends(Ver, Package, - (pkgArch != "none") ? "none" : _config->Find("APT::Architecture"), - Version,Op,Type) == false) + if (NewDepends(Ver,Package,Arch,Version,Op | pkgCache::Dep::ArchSpecific,Type) == false) return false; } + if (Start == Stop) break; } @@ -861,13 +834,13 @@ bool debListParser::ParseProvides(pkgCache::VerIterator &Ver) } else if (archfound != string::npos) { string OtherArch = Package.substr(archfound+1, string::npos); Package = Package.substr(0, archfound); - if (NewProvides(Ver, Package, OtherArch, Version) == false) + if (NewProvides(Ver, Package, OtherArch, Version, pkgCache::Flag::ArchSpecific) == false) return false; } else if ((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign) { - if (NewProvidesAllArch(Ver, Package, Version) == false) + if (NewProvidesAllArch(Ver, Package, Version, 0) == false) return false; } else { - if (NewProvides(Ver, Package, Arch, Version) == false) + if (NewProvides(Ver, Package, Arch, Version, 0) == false) return false; } @@ -879,26 +852,14 @@ bool debListParser::ParseProvides(pkgCache::VerIterator &Ver) if ((Ver->MultiArch & pkgCache::Version::Allowed) == pkgCache::Version::Allowed) { string const Package = string(Ver.ParentPkg().Name()).append(":").append("any"); - return NewProvidesAllArch(Ver, Package, Ver.VerStr()); + return NewProvidesAllArch(Ver, Package, Ver.VerStr(), pkgCache::Flag::MultiArchImplicit); } else if ((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign) - return NewProvidesAllArch(Ver, Ver.ParentPkg().Name(), Ver.VerStr()); + return NewProvidesAllArch(Ver, Ver.ParentPkg().Name(), Ver.VerStr(), pkgCache::Flag::MultiArchImplicit); return true; } /*}}}*/ -// ListParser::NewProvides - add provides for all architectures /*{{{*/ -bool debListParser::NewProvidesAllArch(pkgCache::VerIterator &Ver, string const &Package, - string const &Version) { - for (std::vector<string>::const_iterator a = Architectures.begin(); - a != Architectures.end(); ++a) - { - if (NewProvides(Ver, Package, *a, Version) == false) - return false; - } - return true; -} - /*}}}*/ // ListParser::GrabWord - Matches a word and returns /*{{{*/ // --------------------------------------------------------------------- /* Looks for a word in a list of words - for ParseStatus */ @@ -921,71 +882,7 @@ bool debListParser::GrabWord(string Word,WordList *List,unsigned char &Out) bool debListParser::Step() { iOffset = Tags.Offset(); - while (Tags.Step(Section) == true) - { - /* See if this is the correct Architecture, if it isn't then we - drop the whole section. A missing arch tag only happens (in theory) - inside the Status file, so that is a positive return */ - string const Architecture = Section.FindS("Architecture"); - - if (Arch.empty() == true || Arch == "any" || MultiArchEnabled == false) - { - if (APT::Configuration::checkArchitecture(Architecture) == true) - return true; - /* parse version stanzas without an architecture only in the status file - (and as misfortune bycatch flat-archives) */ - if ((Arch.empty() == true || Arch == "any") && Architecture.empty() == true) - return true; - } - else - { - if (Architecture == Arch) - return true; - - if (Architecture == "all" && Arch == _config->Find("APT::Architecture")) - return true; - } - - iOffset = Tags.Offset(); - } - return false; -} - /*}}}*/ -// ListParser::LoadReleaseInfo - Load the release information /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator &FileI, - FileFd &File, string component) -{ - // apt-secure does no longer download individual (per-section) Release - // file. to provide Component pinning we use the section name now - map_stringitem_t const storage = StoreString(pkgCacheGenerator::MIXED, component); - FileI->Component = storage; - - pkgTagFile TagFile(&File, File.Size()); - pkgTagSection Section; - if (_error->PendingError() == true || TagFile.Step(Section) == false) - return false; - - std::string data; - #define APT_INRELEASE(TYPE, TAG, STORE) \ - data = Section.FindS(TAG); \ - if (data.empty() == false) \ - { \ - map_stringitem_t const storage = StoreString(pkgCacheGenerator::TYPE, data); \ - STORE = storage; \ - } - APT_INRELEASE(MIXED, "Suite", FileI->Archive) - APT_INRELEASE(MIXED, "Component", FileI->Component) - APT_INRELEASE(VERSIONNUMBER, "Version", FileI->Version) - APT_INRELEASE(MIXED, "Origin", FileI->Origin) - APT_INRELEASE(MIXED, "Codename", FileI->Codename) - APT_INRELEASE(MIXED, "Label", FileI->Label) - #undef APT_INRELEASE - Section.FindFlag("NotAutomatic", FileI->Flags, pkgCache::Flag::NotAutomatic); - Section.FindFlag("ButAutomaticUpgrades", FileI->Flags, pkgCache::Flag::ButAutomaticUpgrades); - - return !_error->PendingError(); + return Tags.Step(Section); } /*}}}*/ // ListParser::GetPrio - Convert the priority from a string /*{{{*/ @@ -1000,11 +897,10 @@ unsigned char debListParser::GetPrio(string Str) return Out; } /*}}}*/ -#if APT_PKG_ABI >= 413 bool debListParser::SameVersion(unsigned short const Hash, /*{{{*/ pkgCache::VerIterator const &Ver) { - if (pkgCacheGenerator::ListParser::SameVersion(Hash, Ver) == false) + if (pkgCacheListParser::SameVersion(Hash, Ver) == false) return false; // status file has no (Download)Size, but all others are fair game // status file is parsed last, so the first version we encounter is @@ -1020,11 +916,9 @@ bool debListParser::SameVersion(unsigned short const Hash, /*{{{*/ return true; } /*}}}*/ -#endif - debDebFileParser::debDebFileParser(FileFd *File, std::string const &DebFile) - : debListParser(File, ""), DebFile(DebFile) + : debListParser(File), DebFile(DebFile) { } @@ -1034,7 +928,7 @@ bool debDebFileParser::UsePackage(pkgCache::PkgIterator &Pkg, bool res = debListParser::UsePackage(Pkg, Ver); // we use the full file path as a provides so that the file is found // by its name - if(NewProvidesAllArch(Ver, DebFile, Ver.VerStr()) == false) + if(NewProvides(Ver, DebFile, Pkg.Cache()->NativeArch(), Ver.VerStr(), 0) == false) return false; return res; } diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h index 6279d8399..747e022d8 100644 --- a/apt-pkg/deb/deblistparser.h +++ b/apt-pkg/deb/deblistparser.h @@ -26,7 +26,7 @@ class FileFd; -class APT_HIDDEN debListParser : public pkgCacheGenerator::ListParser +class APT_HIDDEN debListParser : public pkgCacheListParser { public: @@ -39,21 +39,17 @@ class APT_HIDDEN debListParser : public pkgCacheGenerator::ListParser private: /** \brief dpointer placeholder (for later in case we need it) */ - void *d; + void * const d; protected: pkgTagFile Tags; pkgTagSection Section; map_filesize_t iOffset; - std::string Arch; - std::vector<std::string> Architectures; - bool MultiArchEnabled; virtual bool ParseStatus(pkgCache::PkgIterator &Pkg,pkgCache::VerIterator &Ver); bool ParseDepends(pkgCache::VerIterator &Ver,const char *Tag, unsigned int Type); bool ParseProvides(pkgCache::VerIterator &Ver); - bool NewProvidesAllArch(pkgCache::VerIterator &Ver, std::string const &Package, std::string const &Version); static bool GrabWord(std::string Word,WordList *List,unsigned char &Out); APT_HIDDEN unsigned char ParseMultiArch(bool const showErrors); @@ -62,27 +58,25 @@ class APT_HIDDEN debListParser : public pkgCacheGenerator::ListParser APT_PUBLIC static unsigned char GetPrio(std::string Str); // These all operate against the current section - virtual std::string Package(); - virtual std::string Architecture(); - virtual bool ArchitectureAll(); - virtual std::string Version(); - virtual bool NewVersion(pkgCache::VerIterator &Ver); - virtual std::string Description(std::string const &lang); - virtual std::vector<std::string> AvailableDescriptionLanguages(); - virtual MD5SumValue Description_md5(); - virtual unsigned short VersionHash(); -#if APT_PKG_ABI >= 413 - virtual bool SameVersion(unsigned short const Hash, pkgCache::VerIterator const &Ver); -#endif + virtual std::string Package() APT_OVERRIDE; + virtual std::string Architecture() APT_OVERRIDE; + virtual bool ArchitectureAll() APT_OVERRIDE; + virtual std::string Version() APT_OVERRIDE; + virtual bool NewVersion(pkgCache::VerIterator &Ver) APT_OVERRIDE; + virtual std::string Description(std::string const &lang) APT_OVERRIDE; + virtual std::vector<std::string> AvailableDescriptionLanguages() APT_OVERRIDE; + virtual MD5SumValue Description_md5() APT_OVERRIDE; + virtual unsigned short VersionHash() APT_OVERRIDE; + virtual bool SameVersion(unsigned short const Hash, pkgCache::VerIterator const &Ver) APT_OVERRIDE; virtual bool UsePackage(pkgCache::PkgIterator &Pkg, - pkgCache::VerIterator &Ver); - virtual map_filesize_t Offset() {return iOffset;}; - virtual map_filesize_t Size() {return Section.size();}; + pkgCache::VerIterator &Ver) APT_OVERRIDE; + virtual map_filesize_t Offset() APT_OVERRIDE {return iOffset;}; + virtual map_filesize_t Size() APT_OVERRIDE {return Section.size();}; - virtual bool Step(); - - bool LoadReleaseInfo(pkgCache::PkgFileIterator &FileI,FileFd &File, - std::string section); + virtual bool Step() APT_OVERRIDE; + + bool LoadReleaseInfo(pkgCache::RlsFileIterator &FileI,FileFd &File, + std::string const §ion); APT_PUBLIC static const char *ParseDepends(const char *Start,const char *Stop, std::string &Package,std::string &Ver,unsigned int &Op); @@ -99,7 +93,7 @@ class APT_HIDDEN debListParser : public pkgCacheGenerator::ListParser APT_PUBLIC static const char *ConvertRelation(const char *I,unsigned int &Op); - debListParser(FileFd *File, std::string const &Arch = ""); + debListParser(FileFd *File); virtual ~debListParser(); }; @@ -111,18 +105,18 @@ class APT_HIDDEN debDebFileParser : public debListParser public: debDebFileParser(FileFd *File, std::string const &DebFile); virtual bool UsePackage(pkgCache::PkgIterator &Pkg, - pkgCache::VerIterator &Ver); + pkgCache::VerIterator &Ver) APT_OVERRIDE; }; class APT_HIDDEN debTranslationsParser : public debListParser { public: // a translation can never be a real package - virtual std::string Architecture() { return ""; } - virtual std::string Version() { return ""; } + virtual std::string Architecture() APT_OVERRIDE { return ""; } + virtual std::string Version() APT_OVERRIDE { return ""; } - debTranslationsParser(FileFd *File, std::string const &Arch = "") - : debListParser(File, Arch) {}; + debTranslationsParser(FileFd *File) + : debListParser(File) {}; }; #endif diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index aa2db8149..b2e9eeb00 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -1,5 +1,6 @@ #include <config.h> +#include <apt-pkg/error.h> #include <apt-pkg/debmetaindex.h> #include <apt-pkg/debindexfile.h> #include <apt-pkg/strutl.h> @@ -7,44 +8,50 @@ #include <apt-pkg/acquire-item.h> #include <apt-pkg/configuration.h> #include <apt-pkg/aptconfiguration.h> -#include <apt-pkg/indexrecords.h> #include <apt-pkg/sourcelist.h> #include <apt-pkg/hashes.h> -#include <apt-pkg/macros.h> #include <apt-pkg/metaindex.h> +#include <apt-pkg/pkgcachegen.h> +#include <apt-pkg/tagfile.h> +#include <apt-pkg/gpgv.h> +#include <apt-pkg/macros.h> -#include <string.h> #include <map> #include <string> #include <utility> #include <vector> -#include <set> #include <algorithm> -using namespace std; +#include <sys/stat.h> +#include <string.h> + +#include <apti18n.h> -string debReleaseIndex::Info(const char *Type, string const &Section, string const &Arch) const +class APT_HIDDEN debReleaseIndexPrivate /*{{{*/ { - string Info = ::URI::SiteOnly(URI) + ' '; - if (Dist[Dist.size() - 1] == '/') - { - if (Dist != "/") - Info += Dist; - } - else + public: + struct APT_HIDDEN debSectionEntry { - Info += Dist + '/' + Section; - if (Arch.empty() != true) - Info += " " + Arch; - } - Info += " "; - Info += Type; - return Info; -} + std::string Name; + std::vector<std::string> Targets; + std::vector<std::string> Architectures; + std::vector<std::string> Languages; + }; + + std::vector<debSectionEntry> DebEntries; + std::vector<debSectionEntry> DebSrcEntries; -string debReleaseIndex::MetaIndexInfo(const char *Type) const + metaIndex::TriState CheckValidUntil; + time_t ValidUntilMin; + time_t ValidUntilMax; + + debReleaseIndexPrivate() : CheckValidUntil(metaIndex::TRI_UNSET), ValidUntilMin(0), ValidUntilMax(0) {} +}; + /*}}}*/ +// ReleaseIndex::MetaIndex* - display helpers /*{{{*/ +std::string debReleaseIndex::MetaIndexInfo(const char *Type) const { - string Info = ::URI::SiteOnly(URI) + ' '; + std::string Info = ::URI::ArchiveOnly(URI) + ' '; if (Dist[Dist.size() - 1] == '/') { if (Dist != "/") @@ -56,16 +63,20 @@ string debReleaseIndex::MetaIndexInfo(const char *Type) const Info += Type; return Info; } +std::string debReleaseIndex::Describe() const +{ + return MetaIndexInfo("Release"); +} -string debReleaseIndex::MetaIndexFile(const char *Type) const +std::string debReleaseIndex::MetaIndexFile(const char *Type) const { return _config->FindDir("Dir::State::lists") + URItoFileName(MetaIndexURI(Type)); } -string debReleaseIndex::MetaIndexURI(const char *Type) const +std::string debReleaseIndex::MetaIndexURI(const char *Type) const { - string Res; + std::string Res; if (Dist == "/") Res = URI; @@ -77,235 +88,410 @@ string debReleaseIndex::MetaIndexURI(const char *Type) const Res += Type; return Res; } - -std::string debReleaseIndex::LocalFileName() const + /*}}}*/ +// ReleaseIndex Con- and Destructors /*{{{*/ +debReleaseIndex::debReleaseIndex(std::string const &URI, std::string const &Dist) : + metaIndex(URI, Dist, "deb"), d(new debReleaseIndexPrivate()) +{} +debReleaseIndex::debReleaseIndex(std::string const &URI, std::string const &Dist, bool const pTrusted) : + metaIndex(URI, Dist, "deb"), d(new debReleaseIndexPrivate()) { - // see if we have a InRelease file - std::string PathInRelease = MetaIndexFile("InRelease"); - if (FileExists(PathInRelease)) - return PathInRelease; - - // and if not return the normal one - if (FileExists(PathInRelease)) - return MetaIndexFile("Release"); - - return ""; + Trusted = pTrusted ? TRI_YES : TRI_NO; } - -string debReleaseIndex::IndexURISuffix(const char *Type, string const &Section, string const &Arch) const -{ - string Res =""; - if (Dist[Dist.size() - 1] != '/') - { - if (Arch == "native") - Res += Section + "/binary-" + _config->Find("APT::Architecture") + '/'; - else - Res += Section + "/binary-" + Arch + '/'; - } - return Res + Type; +debReleaseIndex::~debReleaseIndex() { + if (d != NULL) + delete d; } - - -string debReleaseIndex::IndexURI(const char *Type, string const &Section, string const &Arch) const + /*}}}*/ +// ReleaseIndex::GetIndexTargets /*{{{*/ +static void GetIndexTargetsFor(char const * const Type, std::string const &URI, std::string const &Dist, + std::vector<debReleaseIndexPrivate::debSectionEntry> const &entries, + std::vector<IndexTarget> &IndexTargets) { - if (Dist[Dist.size() - 1] == '/') + bool const flatArchive = (Dist[Dist.length() - 1] == '/'); + std::string baseURI = URI; + if (flatArchive) { - string Res; if (Dist != "/") - Res = URI + Dist; - else - Res = URI; - return Res + Type; + baseURI += Dist; } else - return URI + "dists/" + Dist + '/' + IndexURISuffix(Type, Section, Arch); - } + baseURI += "dists/" + Dist + "/"; + std::string const Release = (Dist == "/") ? "" : Dist; + std::string const Site = ::URI::ArchiveOnly(URI); + + bool const GzipIndex = _config->FindB("Acquire::GzipIndexes", false); + for (std::vector<debReleaseIndexPrivate::debSectionEntry>::const_iterator E = entries.begin(); E != entries.end(); ++E) + { + for (std::vector<std::string>::const_iterator T = E->Targets.begin(); T != E->Targets.end(); ++T) + { +#define APT_T_CONFIG(X) _config->Find(std::string("Acquire::IndexTargets::") + Type + "::" + *T + "::" + (X)) + std::string const tplMetaKey = APT_T_CONFIG(flatArchive ? "flatMetaKey" : "MetaKey"); + std::string const tplShortDesc = APT_T_CONFIG("ShortDescription"); + std::string const tplLongDesc = "$(SITE) " + APT_T_CONFIG(flatArchive ? "flatDescription" : "Description"); + bool const IsOptional = _config->FindB(std::string("Acquire::IndexTargets::") + Type + "::" + *T + "::Optional", true); + bool const KeepCompressed = _config->FindB(std::string("Acquire::IndexTargets::") + Type + "::" + *T + "::KeepCompressed", GzipIndex); +#undef APT_T_CONFIG + if (tplMetaKey.empty()) + continue; + + for (std::vector<std::string>::const_iterator L = E->Languages.begin(); L != E->Languages.end(); ++L) + { + if (*L == "none" && tplMetaKey.find("$(LANGUAGE)") != std::string::npos) + continue; + + for (std::vector<std::string>::const_iterator A = E->Architectures.begin(); A != E->Architectures.end(); ++A) + { -string debReleaseIndex::SourceIndexURISuffix(const char *Type, const string &Section) const + std::map<std::string, std::string> Options; + Options.insert(std::make_pair("SITE", Site)); + Options.insert(std::make_pair("RELEASE", Release)); + if (tplMetaKey.find("$(COMPONENT)") != std::string::npos) + Options.insert(std::make_pair("COMPONENT", E->Name)); + if (tplMetaKey.find("$(LANGUAGE)") != std::string::npos) + Options.insert(std::make_pair("LANGUAGE", *L)); + if (tplMetaKey.find("$(ARCHITECTURE)") != std::string::npos) + Options.insert(std::make_pair("ARCHITECTURE", *A)); + Options.insert(std::make_pair("BASE_URI", baseURI)); + Options.insert(std::make_pair("REPO_URI", URI)); + Options.insert(std::make_pair("TARGET_OF", "deb-src")); + Options.insert(std::make_pair("CREATED_BY", *T)); + + std::string MetaKey = tplMetaKey; + std::string ShortDesc = tplShortDesc; + std::string LongDesc = tplLongDesc; + for (std::map<std::string, std::string>::const_iterator O = Options.begin(); O != Options.end(); ++O) + { + MetaKey = SubstVar(MetaKey, std::string("$(") + O->first + ")", O->second); + ShortDesc = SubstVar(ShortDesc, std::string("$(") + O->first + ")", O->second); + LongDesc = SubstVar(LongDesc, std::string("$(") + O->first + ")", O->second); + } + IndexTarget Target( + MetaKey, + ShortDesc, + LongDesc, + Options.find("BASE_URI")->second + MetaKey, + IsOptional, + KeepCompressed, + Options + ); + IndexTargets.push_back(Target); + + if (tplMetaKey.find("$(ARCHITECTURE)") == std::string::npos) + break; + + } + + if (tplMetaKey.find("$(LANGUAGE)") == std::string::npos) + break; + + } + + } + } +} +std::vector<IndexTarget> debReleaseIndex::GetIndexTargets() const { - string Res =""; - if (Dist[Dist.size() - 1] != '/') - Res += Section + "/source/"; - return Res + Type; + std::vector<IndexTarget> IndexTargets; + GetIndexTargetsFor("deb-src", URI, Dist, d->DebSrcEntries, IndexTargets); + GetIndexTargetsFor("deb", URI, Dist, d->DebEntries, IndexTargets); + return IndexTargets; } - -string debReleaseIndex::SourceIndexURI(const char *Type, const string &Section) const + /*}}}*/ +void debReleaseIndex::AddComponent(bool const isSrc, std::string const &Name,/*{{{*/ + std::vector<std::string> const &Targets, + std::vector<std::string> const &Architectures, + std::vector<std::string> Languages) { - string Res; - if (Dist[Dist.size() - 1] == '/') - { - if (Dist != "/") - Res = URI + Dist; - else - Res = URI; - return Res + Type; - } + if (Languages.empty() == true) + Languages.push_back("none"); + debReleaseIndexPrivate::debSectionEntry const entry = { + Name, Targets, Architectures, Languages + }; + if (isSrc) + d->DebSrcEntries.push_back(entry); else - return URI + "dists/" + Dist + "/" + SourceIndexURISuffix(Type, Section); + d->DebEntries.push_back(entry); } + /*}}}*/ -string debReleaseIndex::TranslationIndexURISuffix(const char *Type, const string &Section) const +bool debReleaseIndex::Load(std::string const &Filename, std::string * const ErrorText)/*{{{*/ { - string Res =""; - if (Dist[Dist.size() - 1] != '/') - Res += Section + "/i18n/Translation-"; - return Res + Type; -} + LoadedSuccessfully = TRI_NO; + FileFd Fd; + if (OpenMaybeClearSignedFile(Filename, Fd) == false) + return false; -string debReleaseIndex::TranslationIndexURI(const char *Type, const string &Section) const -{ - string Res; - if (Dist[Dist.size() - 1] == '/') + pkgTagFile TagFile(&Fd, Fd.Size()); + if (_error->PendingError() == true) { - if (Dist != "/") - Res = URI + Dist; - else - Res = URI; - return Res + Type; + if (ErrorText != NULL) + strprintf(*ErrorText, _("Unable to parse Release file %s"),Filename.c_str()); + return false; } - else - return URI + "dists/" + Dist + "/" + TranslationIndexURISuffix(Type, Section); -} -debReleaseIndex::debReleaseIndex(string const &URI, string const &Dist) : - metaIndex(URI, Dist, "deb"), Trusted(CHECK_TRUST) -{} + pkgTagSection Section; + const char *Start, *End; + if (TagFile.Step(Section) == false) + { + if (ErrorText != NULL) + strprintf(*ErrorText, _("No sections in Release file %s"), Filename.c_str()); + return false; + } + // FIXME: find better tag name + SupportsAcquireByHash = Section.FindB("Acquire-By-Hash", false); -debReleaseIndex::debReleaseIndex(string const &URI, string const &Dist, bool const Trusted) : - metaIndex(URI, Dist, "deb") { - SetTrusted(Trusted); -} + Suite = Section.FindS("Suite"); + Codename = Section.FindS("Codename"); -debReleaseIndex::~debReleaseIndex() { - for (map<string, vector<debSectionEntry const*> >::const_iterator A = ArchEntries.begin(); - A != ArchEntries.end(); ++A) - for (vector<const debSectionEntry *>::const_iterator S = A->second.begin(); - S != A->second.end(); ++S) - delete *S; -} + bool FoundHashSum = false; + for (int i=0;HashString::SupportedHashes()[i] != NULL; i++) + { + if (!Section.Find(HashString::SupportedHashes()[i], Start, End)) + continue; + + std::string Name; + std::string Hash; + unsigned long long Size; + while (Start < End) + { + if (!parseSumData(Start, End, Name, Hash, Size)) + return false; + + if (Entries.find(Name) == Entries.end()) + { + metaIndex::checkSum *Sum = new metaIndex::checkSum; + Sum->MetaKeyFilename = Name; + Sum->Size = Size; + Sum->Hashes.FileSize(Size); + APT_IGNORE_DEPRECATED(Sum->Hash = HashString(HashString::SupportedHashes()[i],Hash);) + Entries[Name] = Sum; + } + Entries[Name]->Hashes.push_back(HashString(HashString::SupportedHashes()[i],Hash)); + FoundHashSum = true; + } + } + + if(FoundHashSum == false) + { + if (ErrorText != NULL) + strprintf(*ErrorText, _("No Hash entry in Release file %s"), Filename.c_str()); + return false; + } + + std::string const StrDate = Section.FindS("Date"); + if (RFC1123StrToTime(StrDate.c_str(), Date) == false) + { + if (ErrorText != NULL) + strprintf(*ErrorText, _("Invalid 'Date' entry in Release file %s"), Filename.c_str()); + return false; + } + + bool CheckValidUntil = _config->FindB("Acquire::Check-Valid-Until", true); + if (d->CheckValidUntil == metaIndex::TRI_NO) + CheckValidUntil = false; + else if (d->CheckValidUntil == metaIndex::TRI_YES) + CheckValidUntil = true; + + if (CheckValidUntil == true) + { + std::string const Label = Section.FindS("Label"); + std::string const StrValidUntil = Section.FindS("Valid-Until"); -vector <IndexTarget *>* debReleaseIndex::ComputeIndexTargets() const { - vector <IndexTarget *>* IndexTargets = new vector <IndexTarget *>; - - map<string, vector<debSectionEntry const*> >::const_iterator const src = ArchEntries.find("source"); - if (src != ArchEntries.end()) { - vector<debSectionEntry const*> const SectionEntries = src->second; - for (vector<debSectionEntry const*>::const_iterator I = SectionEntries.begin(); - I != SectionEntries.end(); ++I) { - IndexTarget * Target = new IndexTarget(); - Target->ShortDesc = "Sources"; - Target->MetaKey = SourceIndexURISuffix(Target->ShortDesc.c_str(), (*I)->Section); - Target->URI = SourceIndexURI(Target->ShortDesc.c_str(), (*I)->Section); - Target->Description = Info (Target->ShortDesc.c_str(), (*I)->Section); - IndexTargets->push_back (Target); - } - } - - // Only source release - if (IndexTargets->empty() == false && ArchEntries.size() == 1) - return IndexTargets; - - std::set<std::string> sections; - for (map<string, vector<debSectionEntry const*> >::const_iterator a = ArchEntries.begin(); - a != ArchEntries.end(); ++a) { - if (a->first == "source") - continue; - for (vector <const debSectionEntry *>::const_iterator I = a->second.begin(); - I != a->second.end(); ++I) { - IndexTarget * Target = new IndexTarget(); - Target->ShortDesc = "Packages"; - Target->MetaKey = IndexURISuffix(Target->ShortDesc.c_str(), (*I)->Section, a->first); - Target->URI = IndexURI(Target->ShortDesc.c_str(), (*I)->Section, a->first); - Target->Description = Info (Target->ShortDesc.c_str(), (*I)->Section, a->first); - IndexTargets->push_back (Target); - sections.insert((*I)->Section); - } - } - - std::vector<std::string> lang = APT::Configuration::getLanguages(true); - std::vector<std::string>::iterator lend = std::remove(lang.begin(), lang.end(), "none"); - if (lend != lang.end()) - lang.erase(lend); - - if (lang.empty() == true) - return IndexTargets; - - // get the Translation-* files, later we will skip download of non-existent if we have an index - for (std::set<std::string>::const_iterator s = sections.begin(); - s != sections.end(); ++s) { - for (std::vector<std::string>::const_iterator l = lang.begin(); - l != lang.end(); ++l) { - IndexTarget * Target = new OptionalIndexTarget(); - Target->ShortDesc = "Translation-" + *l; - Target->MetaKey = TranslationIndexURISuffix(l->c_str(), *s); - Target->URI = TranslationIndexURI(l->c_str(), *s); - Target->Description = Info (Target->ShortDesc.c_str(), *s); - IndexTargets->push_back(Target); - } - } - - return IndexTargets; + // if we have a Valid-Until header in the Release file, use it as default + if (StrValidUntil.empty() == false) + { + if(RFC1123StrToTime(StrValidUntil.c_str(), ValidUntil) == false) + { + if (ErrorText != NULL) + strprintf(*ErrorText, _("Invalid 'Valid-Until' entry in Release file %s"), Filename.c_str()); + return false; + } + } + // get the user settings for this archive and use what expires earlier + time_t MaxAge = d->ValidUntilMax; + if (MaxAge == 0) + { + MaxAge = _config->FindI("Acquire::Max-ValidTime", 0); + if (Label.empty() == false) + MaxAge = _config->FindI(("Acquire::Max-ValidTime::" + Label).c_str(), MaxAge); + } + time_t MinAge = d->ValidUntilMin; + if (MinAge == 0) + { + MinAge = _config->FindI("Acquire::Min-ValidTime", 0); + if (Label.empty() == false) + MinAge = _config->FindI(("Acquire::Min-ValidTime::" + Label).c_str(), MinAge); + } + + if (MinAge != 0 && ValidUntil != 0) { + time_t const min_date = Date + MinAge; + if (ValidUntil < min_date) + ValidUntil = min_date; + } + if (MaxAge != 0) { + time_t const max_date = Date + MaxAge; + if (ValidUntil == 0 || ValidUntil > max_date) + ValidUntil = max_date; + } + } + + LoadedSuccessfully = TRI_YES; + return true; +} + /*}}}*/ +metaIndex * debReleaseIndex::UnloadedClone() const /*{{{*/ +{ + if (Trusted == TRI_NO) + return new debReleaseIndex(URI, Dist, false); + else if (Trusted == TRI_YES) + return new debReleaseIndex(URI, Dist, true); + else + return new debReleaseIndex(URI, Dist); } /*}}}*/ -bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const +bool debReleaseIndex::parseSumData(const char *&Start, const char *End, /*{{{*/ + std::string &Name, std::string &Hash, unsigned long long &Size) { - bool const tryInRelease = _config->FindB("Acquire::TryInRelease", true); + Name = ""; + Hash = ""; + Size = 0; + /* Skip over the first blank */ + while ((*Start == '\t' || *Start == ' ' || *Start == '\n' || *Start == '\r') + && Start < End) + Start++; + if (Start >= End) + return false; + + /* Move EntryEnd to the end of the first entry (the hash) */ + const char *EntryEnd = Start; + while ((*EntryEnd != '\t' && *EntryEnd != ' ') + && EntryEnd < End) + EntryEnd++; + if (EntryEnd == End) + return false; - indexRecords * const iR = new indexRecords(Dist); - if (Trusted == ALWAYS_TRUSTED) - iR->SetTrusted(true); - else if (Trusted == NEVER_TRUSTED) - iR->SetTrusted(false); + Hash.append(Start, EntryEnd-Start); + /* Skip over intermediate blanks */ + Start = EntryEnd; + while (*Start == '\t' || *Start == ' ') + Start++; + if (Start >= End) + return false; + + EntryEnd = Start; + /* Find the end of the second entry (the size) */ + while ((*EntryEnd != '\t' && *EntryEnd != ' ' ) + && EntryEnd < End) + EntryEnd++; + if (EntryEnd == End) + return false; + + Size = strtoull (Start, NULL, 10); + + /* Skip over intermediate blanks */ + Start = EntryEnd; + while (*Start == '\t' || *Start == ' ') + Start++; + if (Start >= End) + return false; + + EntryEnd = Start; + /* Find the end of the third entry (the filename) */ + while ((*EntryEnd != '\t' && *EntryEnd != ' ' && + *EntryEnd != '\n' && *EntryEnd != '\r') + && EntryEnd < End) + EntryEnd++; + + Name.append(Start, EntryEnd-Start); + Start = EntryEnd; //prepare for the next round + return true; +} + /*}}}*/ + +bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll)/*{{{*/ +{ + std::vector<IndexTarget> const targets = GetIndexTargets(); +#define APT_TARGET(X) IndexTarget("", X, MetaIndexInfo(X), MetaIndexURI(X), false, false, std::map<std::string,std::string>()) + pkgAcqMetaClearSig * const TransactionManager = new pkgAcqMetaClearSig(Owner, + APT_TARGET("InRelease"), APT_TARGET("Release"), APT_TARGET("Release.gpg"), + targets, this); +#undef APT_TARGET // special case for --print-uris - if (GetAll) { - vector <IndexTarget *> *targets = ComputeIndexTargets(); - for (vector <IndexTarget*>::const_iterator Target = targets->begin(); Target != targets->end(); ++Target) { - new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description, - (*Target)->ShortDesc, HashStringList()); - } - delete targets; - - // this is normally created in pkgAcqMetaSig, but if we run - // in --print-uris mode, we add it here - if (tryInRelease == false) - new pkgAcqMetaIndex(Owner, NULL, - MetaIndexURI("Release"), - MetaIndexInfo("Release"), "Release", - MetaIndexURI("Release.gpg"), MetaIndexInfo("Release.gpg"), "Release.gpg", - ComputeIndexTargets(), - iR); + if (GetAll) + { + for (std::vector<IndexTarget>::const_iterator Target = targets.begin(); Target != targets.end(); ++Target) + new pkgAcqIndex(Owner, TransactionManager, *Target); } - if (tryInRelease == true) - new pkgAcqMetaClearSig(Owner, - MetaIndexURI("InRelease"), MetaIndexInfo("InRelease"), "InRelease", - MetaIndexURI("Release"), MetaIndexInfo("Release"), "Release", - MetaIndexURI("Release.gpg"), MetaIndexInfo("Release.gpg"), "Release.gpg", - ComputeIndexTargets(), - iR); - else - new pkgAcqMetaIndex(Owner, NULL, - MetaIndexURI("Release"), MetaIndexInfo("Release"), "Release", - MetaIndexURI("Release.gpg"), MetaIndexInfo("Release.gpg"), "Release.gpg", - ComputeIndexTargets(), - iR); return true; } - -void debReleaseIndex::SetTrusted(bool const Trusted) + /*}}}*/ +// ReleaseIndex::Set* TriState options /*{{{*/ +bool debReleaseIndex::SetTrusted(TriState const pTrusted) { - if (Trusted == true) - this->Trusted = ALWAYS_TRUSTED; - else - this->Trusted = NEVER_TRUSTED; + if (Trusted == TRI_UNSET) + Trusted = pTrusted; + else if (Trusted != pTrusted) + // TRANSLATOR: The first is an option name from sources.list manpage, the other two URI and Suite + return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Trusted", URI.c_str(), Dist.c_str()); + return true; } - +bool debReleaseIndex::SetCheckValidUntil(TriState const pCheckValidUntil) +{ + if (d->CheckValidUntil == TRI_UNSET) + d->CheckValidUntil = pCheckValidUntil; + else if (d->CheckValidUntil != pCheckValidUntil) + return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Check-Valid-Until", URI.c_str(), Dist.c_str()); + return true; +} +bool debReleaseIndex::SetValidUntilMin(time_t const Valid) +{ + if (d->ValidUntilMin == 0) + d->ValidUntilMin = Valid; + else if (d->ValidUntilMin != Valid) + return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Min-ValidTime", URI.c_str(), Dist.c_str()); + return true; +} +bool debReleaseIndex::SetValidUntilMax(time_t const Valid) +{ + if (d->ValidUntilMax == 0) + d->ValidUntilMax = Valid; + else if (d->ValidUntilMax != Valid) + return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Max-ValidTime", URI.c_str(), Dist.c_str()); + return true; +} +bool debReleaseIndex::SetSignedBy(std::string const &pSignedBy) +{ + if (SignedBy.empty() == true && pSignedBy.empty() == false) + { + if (pSignedBy[0] == '/') // no check for existence as we could be chrooting later or such things + ; // absolute path to a keyring file + else + { + // we could go all fancy and allow short/long/string matches as gpgv/apt-key does, + // but fingerprints are harder to fake than the others and this option is set once, + // not interactively all the time so easy to type is not really a concern. + std::string finger = pSignedBy; + finger.erase(std::remove(finger.begin(), finger.end(), ' '), finger.end()); + std::transform(finger.begin(), finger.end(), finger.begin(), ::toupper); + if (finger.length() != 40 || finger.find_first_not_of("0123456789ABCDEF") != std::string::npos) + return _error->Error(_("Invalid value set for option %s concerning source %s %s (%s)"), "Signed-By", URI.c_str(), Dist.c_str(), "not a fingerprint"); + } + SignedBy = pSignedBy; + } + else if (SignedBy != pSignedBy) + return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Signed-By", URI.c_str(), Dist.c_str()); + return true; +} + /*}}}*/ +// ReleaseIndex::IsTrusted /*{{{*/ bool debReleaseIndex::IsTrusted() const { - if (Trusted == ALWAYS_TRUSTED) + if (Trusted == TRI_YES) return true; - else if (Trusted == NEVER_TRUSTED) + else if (Trusted == TRI_NO) return false; @@ -313,236 +499,288 @@ bool debReleaseIndex::IsTrusted() const if(URI.substr(0,strlen("cdrom:")) == "cdrom:") return true; - string VerifiedSigFile = _config->FindDir("Dir::State::lists") + - URItoFileName(MetaIndexURI("Release")) + ".gpg"; - - if (FileExists(VerifiedSigFile)) + if (FileExists(MetaIndexFile("Release.gpg"))) return true; - VerifiedSigFile = _config->FindDir("Dir::State::lists") + - URItoFileName(MetaIndexURI("InRelease")); - - return FileExists(VerifiedSigFile); + return FileExists(MetaIndexFile("InRelease")); } + /*}}}*/ +std::vector <pkgIndexFile *> *debReleaseIndex::GetIndexFiles() /*{{{*/ +{ + if (Indexes != NULL) + return Indexes; -vector <pkgIndexFile *> *debReleaseIndex::GetIndexFiles() { - if (Indexes != NULL) - return Indexes; - - Indexes = new vector <pkgIndexFile*>; - map<string, vector<debSectionEntry const*> >::const_iterator const src = ArchEntries.find("source"); - if (src != ArchEntries.end()) { - vector<debSectionEntry const*> const SectionEntries = src->second; - for (vector<debSectionEntry const*>::const_iterator I = SectionEntries.begin(); - I != SectionEntries.end(); ++I) - Indexes->push_back(new debSourcesIndex (URI, Dist, (*I)->Section, IsTrusted())); - } - - // Only source release - if (Indexes->empty() == false && ArchEntries.size() == 1) - return Indexes; - - std::vector<std::string> const lang = APT::Configuration::getLanguages(true); - map<string, set<string> > sections; - for (map<string, vector<debSectionEntry const*> >::const_iterator a = ArchEntries.begin(); - a != ArchEntries.end(); ++a) { - if (a->first == "source") - continue; - for (vector<debSectionEntry const*>::const_iterator I = a->second.begin(); - I != a->second.end(); ++I) { - Indexes->push_back(new debPackagesIndex (URI, Dist, (*I)->Section, IsTrusted(), a->first)); - sections[(*I)->Section].insert(lang.begin(), lang.end()); - } - } - - for (map<string, set<string> >::const_iterator s = sections.begin(); - s != sections.end(); ++s) - for (set<string>::const_iterator l = s->second.begin(); - l != s->second.end(); ++l) { - if (*l == "none") continue; - Indexes->push_back(new debTranslationsIndex(URI,Dist,s->first,(*l).c_str())); - } - - return Indexes; + Indexes = new std::vector<pkgIndexFile*>(); + std::vector<IndexTarget> const Targets = GetIndexTargets(); + bool const istrusted = IsTrusted(); + for (std::vector<IndexTarget>::const_iterator T = Targets.begin(); T != Targets.end(); ++T) + { + std::string const TargetName = T->Option(IndexTarget::CREATED_BY); + if (TargetName == "Packages") + Indexes->push_back(new debPackagesIndex(*T, istrusted)); + else if (TargetName == "Sources") + Indexes->push_back(new debSourcesIndex(*T, istrusted)); + else if (TargetName == "Translations") + Indexes->push_back(new debTranslationsIndex(*T)); + } + return Indexes; } + /*}}}*/ -void debReleaseIndex::PushSectionEntry(vector<string> const &Archs, const debSectionEntry *Entry) { - for (vector<string>::const_iterator a = Archs.begin(); - a != Archs.end(); ++a) - ArchEntries[*a].push_back(new debSectionEntry(Entry->Section, Entry->IsSrc)); - delete Entry; +static bool ReleaseFileName(debReleaseIndex const * const That, std::string &ReleaseFile)/*{{{*/ +{ + ReleaseFile = That->MetaIndexFile("InRelease"); + bool releaseExists = false; + if (FileExists(ReleaseFile) == true) + releaseExists = true; + else + { + ReleaseFile = That->MetaIndexFile("Release"); + if (FileExists(ReleaseFile)) + releaseExists = true; + } + return releaseExists; } + /*}}}*/ +bool debReleaseIndex::Merge(pkgCacheGenerator &Gen,OpProgress * /*Prog*/) const/*{{{*/ +{ + std::string ReleaseFile; + bool const releaseExists = ReleaseFileName(this, ReleaseFile); -void debReleaseIndex::PushSectionEntry(string const &Arch, const debSectionEntry *Entry) { - ArchEntries[Arch].push_back(Entry); -} + ::URI Tmp(URI); + if (Gen.SelectReleaseFile(ReleaseFile, Tmp.Host) == false) + return _error->Error("Problem with SelectReleaseFile %s", ReleaseFile.c_str()); -void debReleaseIndex::PushSectionEntry(const debSectionEntry *Entry) { - if (Entry->IsSrc == true) - PushSectionEntry("source", Entry); - else { - for (map<string, vector<const debSectionEntry *> >::iterator a = ArchEntries.begin(); - a != ArchEntries.end(); ++a) { - a->second.push_back(Entry); - } - } -} + if (releaseExists == false) + return true; -debReleaseIndex::debSectionEntry::debSectionEntry (string const &Section, - bool const &IsSrc): Section(Section), IsSrc(IsSrc) -{} + FileFd Rel; + // Beware: The 'Release' file might be clearsigned in case the + // signature for an 'InRelease' file couldn't be checked + if (OpenMaybeClearSignedFile(ReleaseFile, Rel) == false) + return false; + if (_error->PendingError() == true) + return false; -class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type + // Store the IMS information + pkgCache::RlsFileIterator File = Gen.GetCurRlsFile(); + pkgCacheGenerator::Dynamic<pkgCache::RlsFileIterator> DynFile(File); + // Rel can't be used as this is potentially a temporary file + struct stat Buf; + if (stat(ReleaseFile.c_str(), &Buf) != 0) + return _error->Errno("fstat", "Unable to stat file %s", ReleaseFile.c_str()); + File->Size = Buf.st_size; + File->mtime = Buf.st_mtime; + + pkgTagFile TagFile(&Rel, Rel.Size()); + pkgTagSection Section; + if (_error->PendingError() == true || TagFile.Step(Section) == false) + return false; + + std::string data; + #define APT_INRELEASE(TYPE, TAG, STORE) \ + data = Section.FindS(TAG); \ + if (data.empty() == false) \ + { \ + map_stringitem_t const storage = Gen.StoreString(pkgCacheGenerator::TYPE, data); \ + STORE = storage; \ + } + APT_INRELEASE(MIXED, "Suite", File->Archive) + APT_INRELEASE(VERSIONNUMBER, "Version", File->Version) + APT_INRELEASE(MIXED, "Origin", File->Origin) + APT_INRELEASE(MIXED, "Codename", File->Codename) + APT_INRELEASE(MIXED, "Label", File->Label) + #undef APT_INRELEASE + Section.FindFlag("NotAutomatic", File->Flags, pkgCache::Flag::NotAutomatic); + Section.FindFlag("ButAutomaticUpgrades", File->Flags, pkgCache::Flag::ButAutomaticUpgrades); + + return !_error->PendingError(); +} + /*}}}*/ +// ReleaseIndex::FindInCache - Find this index /*{{{*/ +pkgCache::RlsFileIterator debReleaseIndex::FindInCache(pkgCache &Cache, bool const ModifyCheck) const { - protected: + std::string ReleaseFile; + bool const releaseExists = ReleaseFileName(this, ReleaseFile); - bool CreateItemInternal(vector<metaIndex *> &List, string const &URI, - string const &Dist, string const &Section, - bool const &IsSrc, map<string, string> const &Options) const + pkgCache::RlsFileIterator File = Cache.RlsFileBegin(); + for (; File.end() == false; ++File) { - // parse arch=, arch+= and arch-= settings - map<string, string>::const_iterator arch = Options.find("arch"); - vector<string> Archs; - if (arch != Options.end()) - Archs = VectorizeString(arch->second, ','); - else - Archs = APT::Configuration::getArchitectures(); + if (File->FileName == 0 || ReleaseFile != File.FileName()) + continue; - if ((arch = Options.find("arch+")) != Options.end()) + // empty means the file does not exist by "design" + if (ModifyCheck == false || (releaseExists == false && File->Size == 0)) + return File; + + struct stat St; + if (stat(File.FileName(),&St) != 0) { - std::vector<std::string> const plusArch = VectorizeString(arch->second, ','); - for (std::vector<std::string>::const_iterator plus = plusArch.begin(); plus != plusArch.end(); ++plus) - if (std::find(Archs.begin(), Archs.end(), *plus) == Archs.end()) - Archs.push_back(*plus); + if (_config->FindB("Debug::pkgCacheGen", false)) + std::clog << "ReleaseIndex::FindInCache - stat failed on " << File.FileName() << std::endl; + return pkgCache::RlsFileIterator(Cache); } - if ((arch = Options.find("arch-")) != Options.end()) + if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime) { - std::vector<std::string> const minusArch = VectorizeString(arch->second, ','); - for (std::vector<std::string>::const_iterator minus = minusArch.begin(); minus != minusArch.end(); ++minus) - { - std::vector<std::string>::iterator kill = std::find(Archs.begin(), Archs.end(), *minus); - if (kill != Archs.end()) - Archs.erase(kill); - } + if (_config->FindB("Debug::pkgCacheGen", false)) + std::clog << "ReleaseIndex::FindInCache - size (" << St.st_size << " <> " << File->Size + << ") or mtime (" << St.st_mtime << " <> " << File->mtime + << ") doesn't match for " << File.FileName() << std::endl; + return pkgCache::RlsFileIterator(Cache); } + return File; + } - map<string, string>::const_iterator const trusted = Options.find("trusted"); + return File; +} + /*}}}*/ - for (vector<metaIndex *>::const_iterator I = List.begin(); +static std::vector<std::string> parsePlusMinusOptions(std::string const &Name, /*{{{*/ + std::map<std::string, std::string> const &Options, std::vector<std::string> const &defaultValues) +{ + std::map<std::string, std::string>::const_iterator val = Options.find(Name); + std::vector<std::string> Values; + if (val != Options.end()) + Values = VectorizeString(val->second, ','); + else + Values = defaultValues; + + if ((val = Options.find(Name + "+")) != Options.end()) + { + std::vector<std::string> const plusArch = VectorizeString(val->second, ','); + for (std::vector<std::string>::const_iterator plus = plusArch.begin(); plus != plusArch.end(); ++plus) + if (std::find(Values.begin(), Values.end(), *plus) == Values.end()) + Values.push_back(*plus); + } + if ((val = Options.find(Name + "-")) != Options.end()) + { + std::vector<std::string> const minusArch = VectorizeString(val->second, ','); + for (std::vector<std::string>::const_iterator minus = minusArch.begin(); minus != minusArch.end(); ++minus) + { + std::vector<std::string>::iterator kill = std::find(Values.begin(), Values.end(), *minus); + if (kill != Values.end()) + Values.erase(kill); + } + } + return Values; +} + /*}}}*/ +class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type /*{{{*/ +{ + metaIndex::TriState GetTriStateOption(std::map<std::string, std::string>const &Options, char const * const name) const + { + std::map<std::string, std::string>::const_iterator const opt = Options.find(name); + if (opt != Options.end()) + return StringToBool(opt->second, false) ? metaIndex::TRI_YES : metaIndex::TRI_NO; + return metaIndex::TRI_DONTCARE; + } + + time_t GetTimeOption(std::map<std::string, std::string>const &Options, char const * const name) const + { + std::map<std::string, std::string>::const_iterator const opt = Options.find(name); + if (opt == Options.end()) + return 0; + return strtoull(opt->second.c_str(), NULL, 10); + } + + protected: + + bool CreateItemInternal(std::vector<metaIndex *> &List, std::string const &URI, + std::string const &Dist, std::string const &Section, + bool const &IsSrc, std::map<std::string, std::string> const &Options) const + { + debReleaseIndex *Deb = NULL; + for (std::vector<metaIndex *>::const_iterator I = List.begin(); I != List.end(); ++I) { // We only worry about debian entries here if (strcmp((*I)->GetType(), "deb") != 0) continue; - debReleaseIndex *Deb = (debReleaseIndex *) (*I); - if (trusted != Options.end()) - Deb->SetTrusted(StringToBool(trusted->second, false)); - /* This check insures that there will be only one Release file queued for all the Packages files and Sources files it corresponds to. */ - if (Deb->GetURI() == URI && Deb->GetDist() == Dist) + if ((*I)->GetURI() == URI && (*I)->GetDist() == Dist) { - if (IsSrc == true) - Deb->PushSectionEntry("source", new debReleaseIndex::debSectionEntry(Section, IsSrc)); - else - { - if (Dist[Dist.size() - 1] == '/') - Deb->PushSectionEntry("any", new debReleaseIndex::debSectionEntry(Section, IsSrc)); - else - Deb->PushSectionEntry(Archs, new debReleaseIndex::debSectionEntry(Section, IsSrc)); - } - return true; + Deb = dynamic_cast<debReleaseIndex*>(*I); + if (Deb != NULL) + break; } } // No currently created Release file indexes this entry, so we create a new one. - debReleaseIndex *Deb; - if (trusted != Options.end()) - Deb = new debReleaseIndex(URI, Dist, StringToBool(trusted->second, false)); - else + if (Deb == NULL) + { Deb = new debReleaseIndex(URI, Dist); + List.push_back(Deb); + } - if (IsSrc == true) - Deb->PushSectionEntry ("source", new debReleaseIndex::debSectionEntry(Section, IsSrc)); + Deb->AddComponent( + IsSrc, + Section, + parsePlusMinusOptions("target", Options, _config->FindVector(std::string("Acquire::IndexTargets::") + Name, "", true)), + parsePlusMinusOptions("arch", Options, APT::Configuration::getArchitectures()), + parsePlusMinusOptions("lang", Options, APT::Configuration::getLanguages(true)) + ); + + if (Deb->SetTrusted(GetTriStateOption(Options, "trusted")) == false || + Deb->SetCheckValidUntil(GetTriStateOption(Options, "check-valid-until")) == false || + Deb->SetValidUntilMax(GetTimeOption(Options, "valid-until-max")) == false || + Deb->SetValidUntilMin(GetTimeOption(Options, "valid-until-min")) == false) + return false; + + std::map<std::string, std::string>::const_iterator const signedby = Options.find("signed-by"); + if (signedby == Options.end()) + { + if (Deb->SetSignedBy("") == false) + return false; + } else { - if (Dist[Dist.size() - 1] == '/') - Deb->PushSectionEntry ("any", new debReleaseIndex::debSectionEntry(Section, IsSrc)); - else - Deb->PushSectionEntry (Archs, new debReleaseIndex::debSectionEntry(Section, IsSrc)); + if (Deb->SetSignedBy(signedby->second) == false) + return false; } - List.push_back(Deb); + return true; } -}; -debDebFileMetaIndex::debDebFileMetaIndex(std::string const &DebFile) - : metaIndex(DebFile, "local-uri", "deb-dist"), DebFile(DebFile) -{ - DebIndex = new debDebPkgFileIndex(DebFile); - Indexes = new vector<pkgIndexFile *>(); - Indexes->push_back(DebIndex); -} - - -class APT_HIDDEN debSLTypeDeb : public debSLTypeDebian + debSLTypeDebian(char const * const Name, char const * const Label) : Type(Name, Label) + { + } +}; + /*}}}*/ +class APT_HIDDEN debSLTypeDeb : public debSLTypeDebian /*{{{*/ { public: - bool CreateItem(vector<metaIndex *> &List, string const &URI, - string const &Dist, string const &Section, - std::map<string, string> const &Options) const + bool CreateItem(std::vector<metaIndex *> &List, std::string const &URI, + std::string const &Dist, std::string const &Section, + std::map<std::string, std::string> const &Options) const APT_OVERRIDE { return CreateItemInternal(List, URI, Dist, Section, false, Options); } - debSLTypeDeb() + debSLTypeDeb() : debSLTypeDebian("deb", "Debian binary tree") { - Name = "deb"; - Label = "Standard Debian binary tree"; - } + } }; - -class APT_HIDDEN debSLTypeDebSrc : public debSLTypeDebian + /*}}}*/ +class APT_HIDDEN debSLTypeDebSrc : public debSLTypeDebian /*{{{*/ { public: - bool CreateItem(vector<metaIndex *> &List, string const &URI, - string const &Dist, string const &Section, - std::map<string, string> const &Options) const + bool CreateItem(std::vector<metaIndex *> &List, std::string const &URI, + std::string const &Dist, std::string const &Section, + std::map<std::string, std::string> const &Options) const APT_OVERRIDE { return CreateItemInternal(List, URI, Dist, Section, true, Options); } - - debSLTypeDebSrc() - { - Name = "deb-src"; - Label = "Standard Debian source tree"; - } -}; -class APT_HIDDEN debSLTypeDebFile : public pkgSourceList::Type -{ - public: - - bool CreateItem(vector<metaIndex *> &List, string const &URI, - string const &/*Dist*/, string const &/*Section*/, - std::map<string, string> const &/*Options*/) const + debSLTypeDebSrc() : debSLTypeDebian("deb-src", "Debian source tree") { - metaIndex *mi = new debDebFileMetaIndex(URI); - List.push_back(mi); - return true; } - - debSLTypeDebFile() - { - Name = "deb-file"; - Label = "Debian Deb File"; - } }; + /*}}}*/ APT_HIDDEN debSLTypeDeb _apt_DebType; APT_HIDDEN debSLTypeDebSrc _apt_DebSrcType; -APT_HIDDEN debSLTypeDebFile _apt_DebFileType; diff --git a/apt-pkg/deb/debmetaindex.h b/apt-pkg/deb/debmetaindex.h index 94d005760..e93959a21 100644 --- a/apt-pkg/deb/debmetaindex.h +++ b/apt-pkg/deb/debmetaindex.h @@ -1,4 +1,3 @@ -// ijones, walters #ifndef PKGLIB_DEBMETAINDEX_H #define PKGLIB_DEBMETAINDEX_H @@ -18,83 +17,52 @@ class pkgAcquire; class pkgIndexFile; -class debDebPkgFileIndex; class IndexTarget; +class pkgCacheGenerator; +class OpProgress; +class debReleaseIndexPrivate; -class APT_HIDDEN debReleaseIndex : public metaIndex { - public: - - class debSectionEntry - { - public: - debSectionEntry (std::string const &Section, bool const &IsSrc); - std::string const Section; - bool const IsSrc; - }; - - private: - /** \brief dpointer placeholder (for later in case we need it) */ - void *d; - std::map<std::string, std::vector<debSectionEntry const*> > ArchEntries; - enum APT_HIDDEN { ALWAYS_TRUSTED, NEVER_TRUSTED, CHECK_TRUST } Trusted; +class APT_HIDDEN debReleaseIndex : public metaIndex +{ + debReleaseIndexPrivate * const d; + APT_HIDDEN bool parseSumData(const char *&Start, const char *End, std::string &Name, + std::string &Hash, unsigned long long &Size); public: + APT_HIDDEN std::string MetaIndexInfo(const char *Type) const; + APT_HIDDEN std::string MetaIndexFile(const char *Types) const; + APT_HIDDEN std::string MetaIndexURI(const char *Type) const; + debReleaseIndex(std::string const &URI, std::string const &Dist); debReleaseIndex(std::string const &URI, std::string const &Dist, bool const Trusted); virtual ~debReleaseIndex(); - virtual std::string ArchiveURI(std::string const &File) const {return URI + File;}; - virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false) const; - std::vector <IndexTarget *>* ComputeIndexTargets() const; - std::string Info(const char *Type, std::string const &Section, std::string const &Arch="") const; + virtual std::string ArchiveURI(std::string const &File) const APT_OVERRIDE {return URI + File;}; + virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false) APT_OVERRIDE; + virtual std::vector<IndexTarget> GetIndexTargets() const APT_OVERRIDE; - std::string MetaIndexInfo(const char *Type) const; - std::string MetaIndexFile(const char *Types) const; - std::string MetaIndexURI(const char *Type) const; + virtual std::string Describe() const APT_OVERRIDE; + virtual pkgCache::RlsFileIterator FindInCache(pkgCache &Cache, bool const ModifyCheck) const APT_OVERRIDE; + virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const APT_OVERRIDE; -#if APT_PKG_ABI >= 413 - virtual -#endif - std::string LocalFileName() const; - - std::string IndexURI(const char *Type, std::string const &Section, std::string const &Arch="native") const; - std::string IndexURISuffix(const char *Type, std::string const &Section, std::string const &Arch="native") const; - std::string SourceIndexURI(const char *Type, const std::string &Section) const; - std::string SourceIndexURISuffix(const char *Type, const std::string &Section) const; - std::string TranslationIndexURI(const char *Type, const std::string &Section) const; - std::string TranslationIndexURISuffix(const char *Type, const std::string &Section) const; - virtual std::vector <pkgIndexFile *> *GetIndexFiles(); - - void SetTrusted(bool const Trusted); - virtual bool IsTrusted() const; - - void PushSectionEntry(std::vector<std::string> const &Archs, const debSectionEntry *Entry); - void PushSectionEntry(std::string const &Arch, const debSectionEntry *Entry); - void PushSectionEntry(const debSectionEntry *Entry); -}; + virtual bool Load(std::string const &Filename, std::string * const ErrorText) APT_OVERRIDE; + virtual metaIndex * UnloadedClone() const APT_OVERRIDE; -class APT_HIDDEN debDebFileMetaIndex : public metaIndex -{ - private: - std::string DebFile; - debDebPkgFileIndex *DebIndex; - public: - virtual std::string ArchiveURI(std::string const& /*File*/) const { - return DebFile; - } - virtual bool GetIndexes(pkgAcquire* /*Owner*/, const bool& /*GetAll=false*/) const { - return true; - } - virtual std::vector<pkgIndexFile *> *GetIndexFiles() { - return Indexes; - } - virtual bool IsTrusted() const { - return true; - } - debDebFileMetaIndex(std::string const &DebFile); - virtual ~debDebFileMetaIndex() {}; + virtual std::vector <pkgIndexFile *> *GetIndexFiles() APT_OVERRIDE; + + bool SetTrusted(TriState const Trusted); + bool SetCheckValidUntil(TriState const Trusted); + bool SetValidUntilMin(time_t const Valid); + bool SetValidUntilMax(time_t const Valid); + bool SetSignedBy(std::string const &SignedBy); + + virtual bool IsTrusted() const APT_OVERRIDE; + void AddComponent(bool const isSrc, std::string const &Name, + std::vector<std::string> const &Targets, + std::vector<std::string> const &Architectures, + std::vector<std::string> Languages); }; #endif diff --git a/apt-pkg/deb/debrecords.cc b/apt-pkg/deb/debrecords.cc index 335bcfda0..d78a7e2e0 100644 --- a/apt-pkg/deb/debrecords.cc +++ b/apt-pkg/deb/debrecords.cc @@ -34,7 +34,7 @@ using std::string; // RecordParser::debRecordParser - Constructor /*{{{*/ debRecordParser::debRecordParser(string FileName,pkgCache &Cache) : - debRecordParserBase(), File(FileName, FileFd::ReadOnly, FileFd::Extension), + debRecordParserBase(), d(NULL), File(FileName, FileFd::ReadOnly, FileFd::Extension), Tags(&File, std::max(Cache.Head().MaxVerFileSize, Cache.Head().MaxDescFileSize) + 200) { } @@ -42,15 +42,20 @@ debRecordParser::debRecordParser(string FileName,pkgCache &Cache) : // RecordParser::Jump - Jump to a specific record /*{{{*/ bool debRecordParser::Jump(pkgCache::VerFileIterator const &Ver) { + if (Ver.end() == true) + return false; return Tags.Jump(Section,Ver->Offset); } bool debRecordParser::Jump(pkgCache::DescFileIterator const &Desc) { + if (Desc.end() == true) + return false; return Tags.Jump(Section,Desc->Offset); } /*}}}*/ debRecordParser::~debRecordParser() {} +debRecordParserBase::debRecordParserBase() : Parser(), d(NULL) {} // RecordParserBase::FileName - Return the archive filename on the site /*{{{*/ string debRecordParserBase::FileName() { @@ -207,3 +212,9 @@ bool debDebFileRecordParser::LoadContent() return _error->Error(_("Unable to parse package file %s (%d)"), debFileName.c_str(), 3); return true; } +bool debDebFileRecordParser::Jump(pkgCache::VerFileIterator const &) { return LoadContent(); } +bool debDebFileRecordParser::Jump(pkgCache::DescFileIterator const &) { return LoadContent(); } +std::string debDebFileRecordParser::FileName() { return debFileName; } + +debDebFileRecordParser::debDebFileRecordParser(std::string FileName) : debRecordParserBase(), d(NULL), debFileName(FileName) {} +debDebFileRecordParser::~debDebFileRecordParser() {} diff --git a/apt-pkg/deb/debrecords.h b/apt-pkg/deb/debrecords.h index 38e071940..7fc82a88d 100644 --- a/apt-pkg/deb/debrecords.h +++ b/apt-pkg/deb/debrecords.h @@ -27,41 +27,43 @@ class APT_HIDDEN debRecordParserBase : public pkgRecords::Parser { + void * const d; protected: pkgTagSection Section; public: // These refer to the archive file for the Version - virtual std::string FileName(); - virtual std::string SourcePkg(); - virtual std::string SourceVer(); + virtual std::string FileName() APT_OVERRIDE; + virtual std::string SourcePkg() APT_OVERRIDE; + virtual std::string SourceVer() APT_OVERRIDE; - virtual HashStringList Hashes() const; + virtual HashStringList Hashes() const APT_OVERRIDE; // These are some general stats about the package - virtual std::string Maintainer(); - virtual std::string ShortDesc(std::string const &lang); - virtual std::string LongDesc(std::string const &lang); - virtual std::string Name(); - virtual std::string Homepage(); + virtual std::string Maintainer() APT_OVERRIDE; + virtual std::string ShortDesc(std::string const &lang) APT_OVERRIDE; + virtual std::string LongDesc(std::string const &lang) APT_OVERRIDE; + virtual std::string Name() APT_OVERRIDE; + virtual std::string Homepage() APT_OVERRIDE; // An arbitrary custom field - virtual std::string RecordField(const char *fieldName); + virtual std::string RecordField(const char *fieldName) APT_OVERRIDE; - virtual void GetRec(const char *&Start,const char *&Stop); + virtual void GetRec(const char *&Start,const char *&Stop) APT_OVERRIDE; - debRecordParserBase() : Parser() {} + debRecordParserBase(); virtual ~debRecordParserBase(); }; class APT_HIDDEN debRecordParser : public debRecordParserBase { + void * const d; protected: FileFd File; pkgTagFile Tags; - virtual bool Jump(pkgCache::VerFileIterator const &Ver); - virtual bool Jump(pkgCache::DescFileIterator const &Desc); + virtual bool Jump(pkgCache::VerFileIterator const &Ver) APT_OVERRIDE; + virtual bool Jump(pkgCache::DescFileIterator const &Desc) APT_OVERRIDE; public: debRecordParser(std::string FileName,pkgCache &Cache); @@ -71,20 +73,21 @@ class APT_HIDDEN debRecordParser : public debRecordParserBase // custom record parser that reads deb files directly class APT_HIDDEN debDebFileRecordParser : public debRecordParserBase { + void * const d; std::string debFileName; std::string controlContent; APT_HIDDEN bool LoadContent(); protected: // single file files, so no jumping whatsoever - bool Jump(pkgCache::VerFileIterator const &) { return LoadContent(); } - bool Jump(pkgCache::DescFileIterator const &) { return LoadContent(); } + bool Jump(pkgCache::VerFileIterator const &) APT_OVERRIDE; + bool Jump(pkgCache::DescFileIterator const &) APT_OVERRIDE; public: - virtual std::string FileName() { return debFileName; } + virtual std::string FileName() APT_OVERRIDE; - debDebFileRecordParser(std::string FileName) - : debRecordParserBase(), debFileName(FileName) {}; + debDebFileRecordParser(std::string FileName); + virtual ~debDebFileRecordParser(); }; #endif diff --git a/apt-pkg/deb/debsrcrecords.cc b/apt-pkg/deb/debsrcrecords.cc index ca6d09896..9404b6421 100644 --- a/apt-pkg/deb/debsrcrecords.cc +++ b/apt-pkg/deb/debsrcrecords.cc @@ -32,6 +32,10 @@ using std::max; using std::string; +debSrcRecordParser::debSrcRecordParser(std::string const &File,pkgIndexFile const *Index) + : Parser(Index), d(NULL), Fd(File,FileFd::ReadOnly, FileFd::Extension), Tags(&Fd,102400), + iOffset(0), Buffer(NULL) {} + // SrcRecordParser::Binaries - Return the binaries field /*{{{*/ // --------------------------------------------------------------------- /* This member parses the binaries field into a pair of class arrays and diff --git a/apt-pkg/deb/debsrcrecords.h b/apt-pkg/deb/debsrcrecords.h index cd246d624..89134af5f 100644 --- a/apt-pkg/deb/debsrcrecords.h +++ b/apt-pkg/deb/debsrcrecords.h @@ -24,7 +24,7 @@ class pkgIndexFile; class APT_HIDDEN debSrcRecordParser : public pkgSrcRecords::Parser { /** \brief dpointer placeholder (for later in case we need it) */ - void *d; + void * const d; protected: FileFd Fd; @@ -36,29 +36,27 @@ class APT_HIDDEN debSrcRecordParser : public pkgSrcRecords::Parser public: - virtual bool Restart() {return Jump(0);}; - virtual bool Step() {iOffset = Tags.Offset(); return Tags.Step(Sect);}; - virtual bool Jump(unsigned long const &Off) {iOffset = Off; return Tags.Jump(Sect,Off);}; + virtual bool Restart() APT_OVERRIDE {return Jump(0);}; + virtual bool Step() APT_OVERRIDE {iOffset = Tags.Offset(); return Tags.Step(Sect);}; + virtual bool Jump(unsigned long const &Off) APT_OVERRIDE {iOffset = Off; return Tags.Jump(Sect,Off);}; - virtual std::string Package() const {return Sect.FindS("Package");}; - virtual std::string Version() const {return Sect.FindS("Version");}; - virtual std::string Maintainer() const {return Sect.FindS("Maintainer");}; - virtual std::string Section() const {return Sect.FindS("Section");}; - virtual const char **Binaries(); - virtual bool BuildDepends(std::vector<BuildDepRec> &BuildDeps, bool const &ArchOnly, bool const &StripMultiArch = true); - virtual unsigned long Offset() {return iOffset;}; - virtual std::string AsStr() + virtual std::string Package() const APT_OVERRIDE {return Sect.FindS("Package");}; + virtual std::string Version() const APT_OVERRIDE {return Sect.FindS("Version");}; + virtual std::string Maintainer() const APT_OVERRIDE {return Sect.FindS("Maintainer");}; + virtual std::string Section() const APT_OVERRIDE {return Sect.FindS("Section");}; + virtual const char **Binaries() APT_OVERRIDE; + virtual bool BuildDepends(std::vector<BuildDepRec> &BuildDeps, bool const &ArchOnly, bool const &StripMultiArch = true) APT_OVERRIDE; + virtual unsigned long Offset() APT_OVERRIDE {return iOffset;}; + virtual std::string AsStr() APT_OVERRIDE { const char *Start=0,*Stop=0; Sect.GetSection(Start,Stop); return std::string(Start,Stop); }; - virtual bool Files(std::vector<pkgSrcRecords::File> &F); + virtual bool Files(std::vector<pkgSrcRecords::File> &F) APT_OVERRIDE; bool Files2(std::vector<pkgSrcRecords::File2> &F); - debSrcRecordParser(std::string const &File,pkgIndexFile const *Index) - : Parser(Index), Fd(File,FileFd::ReadOnly, FileFd::Extension), Tags(&Fd,102400), - iOffset(0), Buffer(NULL) {} + debSrcRecordParser(std::string const &File,pkgIndexFile const *Index); virtual ~debSrcRecordParser(); }; diff --git a/apt-pkg/deb/debsystem.cc b/apt-pkg/deb/debsystem.cc index 9a5da9da1..465e13b9e 100644 --- a/apt-pkg/deb/debsystem.cc +++ b/apt-pkg/deb/debsystem.cc @@ -53,11 +53,8 @@ public: // System::debSystem - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ -debSystem::debSystem() +debSystem::debSystem() : pkgSystem("Debian dpkg interface", &debVS), d(new debSystemPrivate()) { - d = new debSystemPrivate(); - Label = "Debian dpkg interface"; - VS = &debVS; } /*}}}*/ // System::~debSystem - Destructor /*{{{*/ diff --git a/apt-pkg/deb/debsystem.h b/apt-pkg/deb/debsystem.h index 226cd60bf..aed77520e 100644 --- a/apt-pkg/deb/debsystem.h +++ b/apt-pkg/deb/debsystem.h @@ -28,20 +28,20 @@ class debStatusIndex; class debSystem : public pkgSystem { // private d-pointer - debSystemPrivate *d; + debSystemPrivate * const d; APT_HIDDEN bool CheckUpdates(); public: - virtual bool Lock(); - virtual bool UnLock(bool NoErrors = false); - virtual pkgPackageManager *CreatePM(pkgDepCache *Cache) const; - virtual bool Initialize(Configuration &Cnf); - virtual bool ArchiveSupported(const char *Type); - virtual signed Score(Configuration const &Cnf); - virtual bool AddStatusFiles(std::vector<pkgIndexFile *> &List); + virtual bool Lock() APT_OVERRIDE; + virtual bool UnLock(bool NoErrors = false) APT_OVERRIDE; + virtual pkgPackageManager *CreatePM(pkgDepCache *Cache) const APT_OVERRIDE; + virtual bool Initialize(Configuration &Cnf) APT_OVERRIDE; + virtual bool ArchiveSupported(const char *Type) APT_OVERRIDE; + virtual signed Score(Configuration const &Cnf) APT_OVERRIDE; + virtual bool AddStatusFiles(std::vector<pkgIndexFile *> &List) APT_OVERRIDE; virtual bool FindIndex(pkgCache::PkgFileIterator File, - pkgIndexFile *&Found) const; + pkgIndexFile *&Found) const APT_OVERRIDE; debSystem(); virtual ~debSystem(); diff --git a/apt-pkg/deb/debversion.cc b/apt-pkg/deb/debversion.cc index a5eacb7f5..48462c6a2 100644 --- a/apt-pkg/deb/debversion.cc +++ b/apt-pkg/deb/debversion.cc @@ -16,7 +16,6 @@ #include <apt-pkg/pkgcache.h> #include <string.h> -#include <string> #include <stdlib.h> #include <ctype.h> /*}}}*/ @@ -34,29 +33,26 @@ debVersioningSystem::debVersioningSystem() // debVS::CmpFragment - Compare versions /*{{{*/ // --------------------------------------------------------------------- -/* This compares a fragment of the version. This is a slightly adapted - version of what dpkg uses. */ -#define order(x) ((x) == '~' ? -1 \ - : isdigit((x)) ? 0 \ - : !(x) ? 0 \ - : isalpha((x)) ? (x) \ - : (x) + 256) -int debVersioningSystem::CmpFragment(const char *A,const char *AEnd, - const char *B,const char *BEnd) +/* This compares a fragment of the version. This is a slightly adapted + version of what dpkg uses in dpkg/lib/dpkg/version.c. + In particular, the a | b = NULL check is removed as we check this in the + caller, we use an explicit end for a | b strings and we check ~ explicit. */ +static int order(char c) { - if (A >= AEnd && B >= BEnd) + if (isdigit(c)) return 0; - if (A >= AEnd) - { - if (*B == '~') return 1; + else if (isalpha(c)) + return c; + else if (c == '~') return -1; - } - if (B >= BEnd) - { - if (*A == '~') return -1; - return 1; - } - + else if (c) + return c + 256; + else + return 0; +} +int debVersioningSystem::CmpFragment(const char *A,const char *AEnd, + const char *B,const char *BEnd) +{ /* Iterate over the whole string What this does is to split the whole string into groups of numeric and non numeric portions. For instance: @@ -77,19 +73,19 @@ int debVersioningSystem::CmpFragment(const char *A,const char *AEnd, int rc = order(*rhs); if (vc != rc) return vc - rc; - lhs++; rhs++; + ++lhs; ++rhs; } while (*lhs == '0') - lhs++; + ++lhs; while (*rhs == '0') - rhs++; + ++rhs; while (isdigit(*lhs) && isdigit(*rhs)) { if (!first_diff) first_diff = *lhs - *rhs; - lhs++; - rhs++; + ++lhs; + ++rhs; } if (isdigit(*lhs)) diff --git a/apt-pkg/deb/debversion.h b/apt-pkg/deb/debversion.h index 434ff4a2e..db70c8797 100644 --- a/apt-pkg/deb/debversion.h +++ b/apt-pkg/deb/debversion.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: debversion.h,v 1.3 2001/05/03 05:25:04 jgg Exp $ /* ###################################################################### Debian Version - Versioning system for Debian @@ -25,14 +24,14 @@ class debVersioningSystem : public pkgVersioningSystem // Compare versions.. virtual int DoCmpVersion(const char *A,const char *Aend, - const char *B,const char *Bend) APT_PURE; - virtual bool CheckDep(const char *PkgVer,int Op,const char *DepVer) APT_PURE; + const char *B,const char *Bend) APT_OVERRIDE APT_PURE; + virtual bool CheckDep(const char *PkgVer,int Op,const char *DepVer) APT_OVERRIDE APT_PURE; virtual APT_PURE int DoCmpReleaseVer(const char *A,const char *Aend, - const char *B,const char *Bend) + const char *B,const char *Bend) APT_OVERRIDE { return DoCmpVersion(A,Aend,B,Bend); } - virtual std::string UpstreamVersion(const char *A); + virtual std::string UpstreamVersion(const char *A) APT_OVERRIDE; debVersioningSystem(); }; diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index a7a66c75d..6ae85d2ea 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -18,7 +18,6 @@ #include <apt-pkg/fileutl.h> #include <apt-pkg/install-progress.h> #include <apt-pkg/packagemanager.h> -#include <apt-pkg/pkgrecords.h> #include <apt-pkg/strutl.h> #include <apt-pkg/cacheiterators.h> #include <apt-pkg/macros.h> @@ -27,7 +26,6 @@ #include <errno.h> #include <fcntl.h> #include <grp.h> -#include <pty.h> #include <pwd.h> #include <signal.h> #include <stddef.h> @@ -205,8 +203,10 @@ pkgCache::VerIterator FindNowVersion(const pkgCache::PkgIterator &Pkg) for (Ver = Pkg.VersionList(); Ver.end() == false; ++Ver) for (pkgCache::VerFileIterator Vf = Ver.FileList(); Vf.end() == false; ++Vf) for (pkgCache::PkgFileIterator F = Vf.File(); F.end() == false; ++F) - if (F->Archive != 0 && strcmp(F.Archive(), "now") == 0) + { + if (F.Archive() != 0 && strcmp(F.Archive(), "now") == 0) return Ver; + } return Ver; } /*}}}*/ @@ -214,10 +214,9 @@ pkgCache::VerIterator FindNowVersion(const pkgCache::PkgIterator &Pkg) // DPkgPM::pkgDPkgPM - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ -pkgDPkgPM::pkgDPkgPM(pkgDepCache *Cache) - : pkgPackageManager(Cache), pkgFailures(0), PackagesDone(0), PackagesTotal(0) +pkgDPkgPM::pkgDPkgPM(pkgDepCache *Cache) + : pkgPackageManager(Cache),d(new pkgDPkgPMPrivate()), pkgFailures(0), PackagesDone(0), PackagesTotal(0) { - d = new pkgDPkgPMPrivate(); } /*}}}*/ // DPkgPM::pkgDPkgPM - Destructor /*{{{*/ @@ -1483,6 +1482,10 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) a != Args.end(); ++a) clog << *a << ' '; clog << endl; + for (std::vector<char *>::const_iterator p = Packages.begin(); + p != Packages.end(); ++p) + free(*p); + Packages.clear(); continue; } Args.push_back(NULL); @@ -1540,9 +1543,6 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) _exit(100); } - /* No Job Control Stop Env is a magic dpkg var that prevents it - from using sigstop */ - putenv((char *)"DPKG_NO_TSTP=yes"); execvp(Args[0], (char**) &Args[0]); cerr << "Could not exec dpkg!" << endl; _exit(100); @@ -1841,16 +1841,7 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg) time_t now = time(NULL); fprintf(report, "Date: %s" , ctime(&now)); fprintf(report, "Package: %s %s\n", pkgname.c_str(), pkgver.c_str()); -#if APT_PKG_ABI >= 413 fprintf(report, "SourcePackage: %s\n", Ver.SourcePkgName()); -#else - pkgRecords Recs(Cache); - pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList()); - std::string srcpkgname = Parse.SourcePkg(); - if(srcpkgname.empty()) - srcpkgname = pkgname; - fprintf(report, "SourcePackage: %s\n", srcpkgname.c_str()); -#endif fprintf(report, "ErrorMessage:\n %s\n", errormsg); // ensure that the log is flushed diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h index 2a6e7e004..82c1bef5d 100644 --- a/apt-pkg/deb/dpkgpm.h +++ b/apt-pkg/deb/dpkgpm.h @@ -37,7 +37,7 @@ class pkgDPkgPMPrivate; class pkgDPkgPM : public pkgPackageManager { private: - pkgDPkgPMPrivate *d; + pkgDPkgPMPrivate * const d; /** \brief record the disappear action and handle accordingly @@ -120,14 +120,14 @@ class pkgDPkgPM : public pkgPackageManager void ProcessDpkgStatusLine(char *line); // The Actuall installation implementation - virtual bool Install(PkgIterator Pkg,std::string File); - virtual bool Configure(PkgIterator Pkg); - virtual bool Remove(PkgIterator Pkg,bool Purge = false); + virtual bool Install(PkgIterator Pkg,std::string File) APT_OVERRIDE; + virtual bool Configure(PkgIterator Pkg) APT_OVERRIDE; + virtual bool Remove(PkgIterator Pkg,bool Purge = false) APT_OVERRIDE; - virtual bool Go(APT::Progress::PackageManager *progress); - virtual bool Go(int StatusFd=-1); + virtual bool Go(APT::Progress::PackageManager *progress) APT_OVERRIDE; + virtual bool Go(int StatusFd=-1) APT_OVERRIDE; - virtual void Reset(); + virtual void Reset() APT_OVERRIDE; public: diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index b73c336db..39bbe484f 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -13,7 +13,6 @@ #include <apt-pkg/depcache.h> #include <apt-pkg/versionmatch.h> #include <apt-pkg/error.h> -#include <apt-pkg/sptr.h> #include <apt-pkg/fileutl.h> #include <apt-pkg/strutl.h> #include <apt-pkg/configuration.h> @@ -23,6 +22,7 @@ #include <apt-pkg/cacheset.h> #include <apt-pkg/pkgcache.h> #include <apt-pkg/cacheiterators.h> +#include <apt-pkg/cachefile.h> #include <apt-pkg/macros.h> #include <stdio.h> @@ -63,7 +63,7 @@ ConfigValueInSubTree(const char* SubTree, const char *needle) } /*}}}*/ pkgDepCache::ActionGroup::ActionGroup(pkgDepCache &cache) : /*{{{*/ - cache(cache), released(false) + d(NULL), cache(cache), released(false) { ++cache.group_level; } @@ -94,8 +94,10 @@ pkgDepCache::ActionGroup::~ActionGroup() // DepCache::pkgDepCache - Constructors /*{{{*/ // --------------------------------------------------------------------- /* */ -pkgDepCache::pkgDepCache(pkgCache *pCache,Policy *Plcy) : - group_level(0), Cache(pCache), PkgState(0), DepState(0) +pkgDepCache::pkgDepCache(pkgCache * const pCache,Policy * const Plcy) : + group_level(0), Cache(pCache), PkgState(0), DepState(0), + iUsrSize(0), iDownloadSize(0), iInstCount(0), iDelCount(0), iKeepCount(0), + iBrokenCount(0), iPolicyBrokenCount(0), iBadCount(0), d(NULL) { DebugMarker = _config->FindB("Debug::pkgDepCache::Marker", false); DebugAutoInstall = _config->FindB("Debug::pkgDepCache::AutoInstall", false); @@ -118,7 +120,7 @@ pkgDepCache::~pkgDepCache() // DepCache::Init - Generate the initial extra structures. /*{{{*/ // --------------------------------------------------------------------- /* This allocats the extension buffers and initializes them. */ -bool pkgDepCache::Init(OpProgress *Prog) +bool pkgDepCache::Init(OpProgress * const Prog) { // Suppress mark updates during this operation (just in case) and // run a mark operation when Init terminates. @@ -129,7 +131,7 @@ bool pkgDepCache::Init(OpProgress *Prog) PkgState = new StateCache[Head().PackageCount]; DepState = new unsigned char[Head().DependsCount]; memset(PkgState,0,sizeof(*PkgState)*Head().PackageCount); - memset(DepState,0,sizeof(*DepState)*Head().DependsCount); + memset(DepState,0,sizeof(*DepState)*Head().DependsCount); if (Prog != 0) { @@ -137,7 +139,7 @@ bool pkgDepCache::Init(OpProgress *Prog) _("Building dependency tree")); Prog->SubProgress(Head().PackageCount,_("Candidate versions")); } - + /* Set the current state of everything. In this state all of the packages are kept exactly as is. See AllUpgrade */ int Done = 0; @@ -145,7 +147,7 @@ bool pkgDepCache::Init(OpProgress *Prog) { if (Prog != 0 && Done%20 == 0) Prog->Progress(Done); - + // Find the proper cache slot StateCache &State = PkgState[I->ID]; State.iFlags = 0; @@ -154,28 +156,27 @@ bool pkgDepCache::Init(OpProgress *Prog) State.CandidateVer = GetCandidateVer(I); State.InstallVer = I.CurrentVer(); State.Mode = ModeKeep; - + State.Update(I,*this); - } - + } + if (Prog != 0) { - Prog->OverallProgress(Head().PackageCount,2*Head().PackageCount, Head().PackageCount, _("Building dependency tree")); Prog->SubProgress(Head().PackageCount,_("Dependency generation")); } - + Update(Prog); if(Prog != 0) Prog->Done(); return true; -} +} /*}}}*/ -bool pkgDepCache::readStateFile(OpProgress *Prog) /*{{{*/ +bool pkgDepCache::readStateFile(OpProgress * const Prog) /*{{{*/ { FileFd state_file; string const state = _config->FindFile("Dir::State::extended_states"); @@ -183,7 +184,7 @@ bool pkgDepCache::readStateFile(OpProgress *Prog) /*{{{*/ state_file.Open(state, FileFd::ReadOnly); off_t const file_size = state_file.Size(); if(Prog != NULL) - Prog->OverallProgress(0, file_size, 1, + Prog->OverallProgress(0, file_size, 1, _("Reading state information")); pkgTagFile tagfile(&state_file); @@ -227,7 +228,7 @@ bool pkgDepCache::readStateFile(OpProgress *Prog) /*{{{*/ return true; } /*}}}*/ -bool pkgDepCache::writeStateFile(OpProgress * /*prog*/, bool InstalledOnly) /*{{{*/ +bool pkgDepCache::writeStateFile(OpProgress * const /*prog*/, bool const InstalledOnly) /*{{{*/ { bool const debug_autoremove = _config->FindB("Debug::pkgAutoRemove",false); @@ -337,7 +338,7 @@ bool pkgDepCache::writeStateFile(OpProgress * /*prog*/, bool InstalledOnly) /*{{ then walks along the package provides list and checks if each provides will be installed then checks the provides against the dep. Res will be set to the package which was used to satisfy the dep. */ -bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res) +bool pkgDepCache::CheckDep(DepIterator const &Dep,int const Type,PkgIterator &Res) { Res = Dep.TargetPkg(); @@ -346,24 +347,27 @@ bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res) bug. Conflicts may never self match */ if (Dep.IsIgnorable(Res) == false) { - PkgIterator Pkg = Dep.TargetPkg(); // Check the base package - if (Type == NowVersion && Pkg->CurrentVer != 0) - if (Dep.IsSatisfied(Pkg.CurrentVer()) == true) + if (Type == NowVersion) + { + if (Res->CurrentVer != 0 && Dep.IsSatisfied(Res.CurrentVer()) == true) return true; - - if (Type == InstallVersion && PkgState[Pkg->ID].InstallVer != 0) - if (Dep.IsSatisfied(PkgState[Pkg->ID].InstVerIter(*this)) == true) + } + else if (Type == InstallVersion) + { + if (PkgState[Res->ID].InstallVer != 0 && + Dep.IsSatisfied(PkgState[Res->ID].InstVerIter(*this)) == true) return true; - - if (Type == CandidateVersion && PkgState[Pkg->ID].CandidateVer != 0) - if (Dep.IsSatisfied(PkgState[Pkg->ID].CandidateVerIter(*this)) == true) + } + else if (Type == CandidateVersion) + if (PkgState[Res->ID].CandidateVer != 0 && + Dep.IsSatisfied(PkgState[Res->ID].CandidateVerIter(*this)) == true) return true; } - + if (Dep->Type == Dep::Obsoletes) return false; - + // Check the providing packages PrvIterator P = Dep.TargetPkg().ProvidesList(); for (; P.end() != true; ++P) @@ -377,21 +381,19 @@ bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res) if (P.OwnerPkg().CurrentVer() != P.OwnerVer()) continue; } - - if (Type == InstallVersion) + else if (Type == InstallVersion) { StateCache &State = PkgState[P.OwnerPkg()->ID]; if (State.InstallVer != (Version *)P.OwnerVer()) continue; } - - if (Type == CandidateVersion) + else if (Type == CandidateVersion) { StateCache &State = PkgState[P.OwnerPkg()->ID]; if (State.CandidateVer != (Version *)P.OwnerVer()) continue; } - + // Compare the versions. if (Dep.IsSatisfied(P) == true) { @@ -399,7 +401,7 @@ bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res) return true; } } - + return false; } /*}}}*/ @@ -481,47 +483,46 @@ void pkgDepCache::AddStates(const PkgIterator &Pkg, bool const Invert) { signed char const Add = (Invert == false) ? 1 : -1; StateCache &State = PkgState[Pkg->ID]; - + // The Package is broken (either minimal dep or policy dep) if ((State.DepState & DepInstMin) != DepInstMin) iBrokenCount += Add; if ((State.DepState & DepInstPolicy) != DepInstPolicy) iPolicyBrokenCount += Add; - + // Bad state if (Pkg.State() != PkgIterator::NeedsNothing) iBadCount += Add; - + // Not installed if (Pkg->CurrentVer == 0) { if (State.Mode == ModeDelete && (State.iFlags & Purge) == Purge && Pkg.Purge() == false) iDelCount += Add; - + if (State.Mode == ModeInstall) iInstCount += Add; return; } - + // Installed, no upgrade if (State.Status == 0) - { + { if (State.Mode == ModeDelete) iDelCount += Add; else if ((State.iFlags & ReInstall) == ReInstall) iInstCount += Add; - return; } - + // Alll 3 are possible if (State.Mode == ModeDelete) - iDelCount += Add; - if (State.Mode == ModeKeep) + iDelCount += Add; + else if (State.Mode == ModeKeep) iKeepCount += Add; - if (State.Mode == ModeInstall) + else if (State.Mode == ModeInstall) iInstCount += Add; } /*}}}*/ @@ -532,7 +533,6 @@ void pkgDepCache::AddStates(const PkgIterator &Pkg, bool const Invert) void pkgDepCache::BuildGroupOrs(VerIterator const &V) { unsigned char Group = 0; - for (DepIterator D = V.DependsList(); D.end() != true; ++D) { // Build the dependency state. @@ -542,18 +542,18 @@ void pkgDepCache::BuildGroupOrs(VerIterator const &V) right sense for a conflicts group */ if (D.IsNegative() == true) State = ~State; - + // Add to the group if we are within an or.. State &= 0x7; Group |= State; State |= Group << 3; if ((D->CompareOp & Dep::Or) != Dep::Or) Group = 0; - + // Invert for Conflicts if (D.IsNegative() == true) State = ~State; - } + } } /*}}}*/ // DepCache::VersionState - Perform a pass over a dependency list /*{{{*/ @@ -562,34 +562,31 @@ void pkgDepCache::BuildGroupOrs(VerIterator const &V) state of the list, filtering it through both a Min check and a Policy check. The return result will have SetMin/SetPolicy low if a check fails. It uses the DepState cache for it's computations. */ -unsigned char pkgDepCache::VersionState(DepIterator D,unsigned char Check, - unsigned char SetMin, - unsigned char SetPolicy) +unsigned char pkgDepCache::VersionState(DepIterator D, unsigned char const Check, + unsigned char const SetMin, + unsigned char const SetPolicy) const { unsigned char Dep = 0xFF; - while (D.end() != true) { - // Compute a single dependency element (glob or) - DepIterator Start = D; - unsigned char State = 0; - for (bool LastOR = true; D.end() == false && LastOR == true; ++D) - { - State |= DepState[D->ID]; - LastOR = (D->CompareOp & Dep::Or) == Dep::Or; - } - + // the last or-dependency has the state of all previous or'ed + DepIterator Start, End; + D.GlobOr(Start, End); + // ignore if we are called with Dep{Install,…} or DepG{Install,…} + // the later would be more correct, but the first is what we get + unsigned char const State = DepState[End->ID] | (DepState[End->ID] >> 3); + // Minimum deps that must be satisfied to have a working package if (Start.IsCritical() == true) + { if ((State & Check) != Check) - Dep &= ~SetMin; - + return Dep &= ~(SetMin | SetPolicy); + } // Policy deps that must be satisfied to install the package - if (IsImportantDep(Start) == true && + else if (IsImportantDep(Start) == true && (State & Check) != Check) Dep &= ~SetPolicy; } - return Dep; } /*}}}*/ @@ -598,17 +595,17 @@ unsigned char pkgDepCache::VersionState(DepIterator D,unsigned char Check, /* This is the main dependency computation bit. It computes the 3 main results for a dependencys, Now, Install and Candidate. Callers must invert the result if dealing with conflicts. */ -unsigned char pkgDepCache::DependencyState(DepIterator &D) +unsigned char pkgDepCache::DependencyState(DepIterator const &D) { unsigned char State = 0; - + if (CheckDep(D,NowVersion) == true) State |= DepNow; if (CheckDep(D,InstallVersion) == true) State |= DepInstall; if (CheckDep(D,CandidateVersion) == true) State |= DepCVer; - + return State; } /*}}}*/ @@ -617,7 +614,7 @@ unsigned char pkgDepCache::DependencyState(DepIterator &D) /* This determines the combined dependency representation of a package for its two states now and install. This is done by using the pre-generated dependency information. */ -void pkgDepCache::UpdateVerState(PkgIterator Pkg) +void pkgDepCache::UpdateVerState(PkgIterator const &Pkg) { // Empty deps are always true StateCache &State = PkgState[Pkg->ID]; @@ -651,7 +648,7 @@ void pkgDepCache::UpdateVerState(PkgIterator Pkg) // --------------------------------------------------------------------- /* This will figure out the state of all the packages and all the dependencies based on the current policy. */ -void pkgDepCache::Update(OpProgress *Prog) +void pkgDepCache::Update(OpProgress * const Prog) { iUsrSize = 0; iDownloadSize = 0; @@ -838,6 +835,41 @@ bool pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge, ActionGroup group(*this); + if (FromUser == false) + { + VerIterator const PV = P.InstVerIter(*this); + if (PV.end() == false) + { + // removed metapackages mark their dependencies as manual to prevent in "desktop depends browser, texteditor" + // the removal of browser to suggest the removal of desktop and texteditor. + // We ignore the auto-bit here as we can't deal with metapackage cascardes otherwise. + // We do not check for or-groups here as we don't know which package takes care of + // providing the feature the user likes e.g.: browser1 | browser2 | browser3 + // Temporary removals are effected by this as well, which is bad, but unlikely in practice + bool const PinNeverMarkAutoSection = (PV->Section != 0 && ConfigValueInSubTree("APT::Never-MarkAuto-Sections", PV.Section())); + if (PinNeverMarkAutoSection) + { + for (DepIterator D = PV.DependsList(); D.end() != true; ++D) + { + if (D.IsMultiArchImplicit() == true || D.IsNegative() == true || IsImportantDep(D) == false) + continue; + + pkgCacheFile CacheFile(this); + APT::VersionList verlist = APT::VersionList::FromDependency(CacheFile, D, APT::CacheSetHelper::INSTALLED); + for (auto const &V : verlist) + { + PkgIterator const DP = V.ParentPkg(); + if(DebugAutoInstall == true) + std::clog << OutputInDepth(Depth) << "Setting " << DP.FullName(false) << " NOT as auto-installed (direct " + << D.DepType() << " of " << Pkg.FullName(false) << " which is in APT::Never-MarkAuto-Sections)" << std::endl; + + MarkAuto(DP, false); + } + } + } + } + } + if (DebugMarker == true) std::clog << OutputInDepth(Depth) << (rPurge ? "MarkPurge " : "MarkDelete ") << Pkg << " FU=" << FromUser << std::endl; @@ -947,7 +979,7 @@ bool pkgDepCache::IsModeChangeOk(ModeList const mode, PkgIterator const &Pkg, /* */ struct CompareProviders { pkgCache::PkgIterator const Pkg; - CompareProviders(pkgCache::DepIterator const &Dep) : Pkg(Dep.TargetPkg()) {}; + explicit CompareProviders(pkgCache::DepIterator const &Dep) : Pkg(Dep.TargetPkg()) {}; //bool operator() (APT::VersionList::iterator const &AV, APT::VersionList::iterator const &BV) bool operator() (pkgCache::VerIterator const &AV, pkgCache::VerIterator const &BV) { @@ -1095,7 +1127,28 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, if (DebugMarker == true) std::clog << OutputInDepth(Depth) << "MarkInstall " << Pkg << " FU=" << FromUser << std::endl; - DepIterator Dep = P.InstVerIter(*this).DependsList(); + bool MoveAutoBitToDependencies = false; + VerIterator const PV = P.InstVerIter(*this); + if (unlikely(PV.end() == true)) + return false; + else if (PV->Section != 0 && (P.Flags & Flag::Auto) != Flag::Auto) + { + VerIterator const CurVer = Pkg.CurrentVer(); + if (CurVer.end() == false && CurVer->Section != 0 && strcmp(CurVer.Section(), PV.Section()) != 0) + { + bool const CurVerInMoveSection = ConfigValueInSubTree("APT::Move-Autobit-Sections", CurVer.Section()); + bool const InstVerInMoveSection = ConfigValueInSubTree("APT::Move-Autobit-Sections", PV.Section()); + MoveAutoBitToDependencies = (CurVerInMoveSection == false && InstVerInMoveSection == true); + if (MoveAutoBitToDependencies == true) + { + if(DebugAutoInstall == true) + std::clog << OutputInDepth(Depth) << "Setting " << Pkg.FullName(false) << " as auto-installed, moving manual to its dependencies" << std::endl; + MarkAuto(Pkg, true); + } + } + } + + DepIterator Dep = PV.DependsList(); for (; Dep.end() != true;) { // Grok or groups @@ -1187,18 +1240,8 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, fixing the problem for "positive" dependencies */ if (Start.IsNegative() == false && (DepState[Start->ID] & DepCVer) == DepCVer) { - APT::VersionList verlist; - pkgCache::VerIterator Cand = PkgState[Start.TargetPkg()->ID].CandidateVerIter(*this); - if (Cand.end() == false && Start.IsSatisfied(Cand) == true) - verlist.insert(Cand); - for (PrvIterator Prv = Start.TargetPkg().ProvidesList(); Prv.end() != true; ++Prv) - { - pkgCache::VerIterator V = Prv.OwnerVer(); - pkgCache::VerIterator Cand = PkgState[Prv.OwnerPkg()->ID].CandidateVerIter(*this); - if (Cand.end() == true || V != Cand || Start.IsSatisfied(Prv) == false) - continue; - verlist.insert(Cand); - } + pkgCacheFile CacheFile(this); + APT::VersionList verlist = APT::VersionList::FromDependency(CacheFile, Start, APT::CacheSetHelper::CANDIDATE); CompareProviders comp(Start); do { @@ -1217,14 +1260,17 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, verlist.erase(InstVer); continue; } + // now check if we should consider it a automatic dependency or not - if(InstPkg->CurrentVer == 0 && InstVer->Section != 0 && ConfigValueInSubTree("APT::Never-MarkAuto-Sections", InstVer.Section())) + if(InstPkg->CurrentVer == 0 && MoveAutoBitToDependencies) { if(DebugAutoInstall == true) - std::clog << OutputInDepth(Depth) << "Setting NOT as auto-installed (direct " - << Start.DepType() << " of pkg in APT::Never-MarkAuto-Sections)" << std::endl; + std::clog << OutputInDepth(Depth) << "Setting " << InstPkg.FullName(false) << " NOT as auto-installed (direct " + << Start.DepType() << " of " << Pkg.FullName(false) << " which is manual and in APT::Move-Autobit-Sections)" << std::endl; MarkAuto(InstPkg, false); } + + break; } while(true); continue; @@ -1234,9 +1280,9 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, Otherwise we remove the offender if needed */ else if (Start.IsNegative() == true && Start->Type != pkgCache::Dep::Obsoletes) { - SPtrArray<Version *> List = Start.AllTargets(); + std::unique_ptr<Version *[]> List(Start.AllTargets()); pkgCache::PkgIterator TrgPkg = Start.TargetPkg(); - for (Version **I = List; *I != 0; I++) + for (Version **I = List.get(); *I != 0; I++) { VerIterator Ver(*this,*I); PkgIterator Pkg = Ver.ParentPkg(); @@ -1662,10 +1708,10 @@ const char *pkgDepCache::StateCache::StripEpoch(const char *Ver) return 0; // Strip any epoch - for (const char *I = Ver; *I != 0; I++) - if (*I == ':') - return I + 1; - return Ver; + char const * const I = strchr(Ver, ':'); + if (I == nullptr) + return Ver; + return I + 1; } /*}}}*/ // Policy::GetCandidateVer - Returns the Candidate install version /*{{{*/ @@ -1685,13 +1731,13 @@ pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator const &Pk for (VerFileIterator J = I.FileList(); J.end() == false; ++J) { - if ((J.File()->Flags & Flag::NotSource) != 0) + if (J.File().Flagged(Flag::NotSource)) continue; /* Stash the highest version of a not-automatic source, we use it if there is nothing better */ - if ((J.File()->Flags & Flag::NotAutomatic) != 0 || - (J.File()->Flags & Flag::ButAutomaticUpgrades) != 0) + if (J.File().Flagged(Flag::NotAutomatic) || + J.File().Flagged(Flag::ButAutomaticUpgrades)) { if (Last.end() == true) Last = I; @@ -1708,17 +1754,17 @@ pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator const &Pk // Policy::IsImportantDep - True if the dependency is important /*{{{*/ // --------------------------------------------------------------------- /* */ -bool pkgDepCache::Policy::IsImportantDep(DepIterator const &Dep) +bool pkgDepCache::Policy::IsImportantDep(DepIterator const &Dep) const { if(Dep.IsCritical()) return true; - else if(Dep->Type == pkgCache::Dep::Recommends) + else if(Dep->Type == pkgCache::Dep::Recommends) { if (InstallRecommends) return true; // we suport a special mode to only install-recommends for certain // sections - // FIXME: this is a meant as a temporarly solution until the + // FIXME: this is a meant as a temporarly solution until the // recommends are cleaned up const char *sec = Dep.ParentVer().Section(); if (sec && ConfigValueInSubTree("APT::Install-Recommends-Sections", sec)) @@ -1733,6 +1779,8 @@ bool pkgDepCache::Policy::IsImportantDep(DepIterator const &Dep) // Policy::GetPriority - Get the priority of the package pin /*{{{*/ APT_CONST signed short pkgDepCache::Policy::GetPriority(pkgCache::PkgIterator const &/*Pkg*/) { return 0; } +APT_CONST signed short pkgDepCache::Policy::GetPriority(pkgCache::VerIterator const &/*Ver*/, bool /*ConsiderFiles*/) +{ return 0; } APT_CONST signed short pkgDepCache::Policy::GetPriority(pkgCache::PkgFileIterator const &/*File*/) { return 0; } /*}}}*/ @@ -1764,24 +1812,22 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc) if (_config->Find("APT::Solver", "internal") != "internal") return true; - bool follow_recommends; - bool follow_suggests; - bool debug_autoremove = _config->FindB("Debug::pkgAutoRemove",false); + bool const debug_autoremove = _config->FindB("Debug::pkgAutoRemove",false); // init the states - for(PkgIterator p = PkgBegin(); !p.end(); ++p) + map_id_t const PackagesCount = Head().PackageCount; + for(map_id_t i = 0; i < PackagesCount; ++i) { - PkgState[p->ID].Marked = false; - PkgState[p->ID].Garbage = false; - - // debug output - if(debug_autoremove && PkgState[p->ID].Flags & Flag::Auto) - std::clog << "AutoDep: " << p.FullName() << std::endl; + PkgState[i].Marked = false; + PkgState[i].Garbage = false; } + if (debug_autoremove) + for(PkgIterator p = PkgBegin(); !p.end(); ++p) + if(PkgState[p->ID].Flags & Flag::Auto) + std::clog << "AutoDep: " << p.FullName() << std::endl; - // init vars - follow_recommends = MarkFollowsRecommends(); - follow_suggests = MarkFollowsSuggests(); + bool const follow_recommends = MarkFollowsRecommends(); + bool const follow_suggests = MarkFollowsSuggests(); // do the mark part, this is the core bit of the algorithm for(PkgIterator p = PkgBegin(); !p.end(); ++p) @@ -1965,7 +2011,7 @@ bool pkgDepCache::MarkAndSweep(InRootSetFunc &rootFunc) } bool pkgDepCache::MarkAndSweep() { - std::auto_ptr<InRootSetFunc> f(GetRootSetFunc()); + std::unique_ptr<InRootSetFunc> f(GetRootSetFunc()); if(f.get() != NULL) return MarkAndSweep(*f.get()); else diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h index 20d263c67..ba997c8a6 100644 --- a/apt-pkg/depcache.h +++ b/apt-pkg/depcache.h @@ -1,6 +1,5 @@ // -*- mode: c++; mode: fold -*- // Description /*{{{*/ -// $Id: depcache.h,v 1.14 2001/02/20 07:03:17 jgg Exp $ /* ###################################################################### DepCache - Dependency Extension data for the cache @@ -164,6 +163,7 @@ class pkgDepCache : protected pkgCache::Namespace */ class ActionGroup { + void * const d; pkgDepCache &cache; bool released; @@ -179,7 +179,7 @@ class pkgDepCache : protected pkgCache::Namespace * As long as this object exists, no automatic cleanup * operations will be undertaken. */ - ActionGroup(pkgDepCache &cache); + explicit ActionGroup(pkgDepCache &cache); /** \brief Clean up the action group before it is destroyed. * @@ -192,7 +192,7 @@ class pkgDepCache : protected pkgCache::Namespace * If this is the last action group, the automatic cache * cleanup operations will be undertaken. */ - ~ActionGroup(); + virtual ~ActionGroup(); }; /** \brief Returns \b true for packages matching a regular @@ -204,7 +204,7 @@ class pkgDepCache : protected pkgCache::Namespace DefaultRootSetFunc() : Configuration::MatchAgainstConfig("APT::NeverAutoRemove") {}; virtual ~DefaultRootSetFunc() {}; - bool InRootSet(const pkgCache::PkgIterator &pkg) { return pkg.end() == false && Match(pkg.Name()); }; + bool InRootSet(const pkgCache::PkgIterator &pkg) APT_OVERRIDE { return pkg.end() == false && Match(pkg.Name()); }; }; struct StateCache @@ -250,7 +250,7 @@ class pkgDepCache : protected pkgCache::Namespace inline bool Keep() const {return Mode == ModeKeep;}; inline bool Protect() const {return (iFlags & Protected) == Protected;}; inline bool Upgrade() const {return Status > 0 && Mode == ModeInstall;}; - inline bool Upgradable() const {return Status >= 1;}; + inline bool Upgradable() const {return Status >= 1 && CandidateVer != NULL;}; inline bool Downgrade() const {return Status < 0 && Mode == ModeInstall;}; inline bool Held() const {return Status != 0 && Keep();}; inline bool NowBroken() const {return (DepState & DepNowMin) != DepNowMin;}; @@ -267,7 +267,7 @@ class pkgDepCache : protected pkgCache::Namespace // Helper functions void BuildGroupOrs(VerIterator const &V); - void UpdateVerState(PkgIterator Pkg); + void UpdateVerState(PkgIterator const &Pkg); // User Policy control class Policy @@ -279,8 +279,9 @@ class pkgDepCache : protected pkgCache::Namespace } virtual VerIterator GetCandidateVer(PkgIterator const &Pkg); - virtual bool IsImportantDep(DepIterator const &Dep); + virtual bool IsImportantDep(DepIterator const &Dep) const; virtual signed short GetPriority(PkgIterator const &Pkg); + virtual signed short GetPriority(VerIterator const &Ver, bool ConsiderFiles=true); virtual signed short GetPriority(PkgFileIterator const &File); virtual ~Policy() {}; @@ -323,18 +324,18 @@ class pkgDepCache : protected pkgCache::Namespace Policy *LocalPolicy; // Check for a matching provides - bool CheckDep(DepIterator Dep,int Type,PkgIterator &Res); - inline bool CheckDep(DepIterator Dep,int Type) + bool CheckDep(DepIterator const &Dep,int const Type,PkgIterator &Res); + inline bool CheckDep(DepIterator const &Dep,int const Type) { PkgIterator Res(*this,0); return CheckDep(Dep,Type,Res); } // Computes state information for deps and versions (w/o storing) - unsigned char DependencyState(DepIterator &D); - unsigned char VersionState(DepIterator D,unsigned char Check, - unsigned char SetMin, - unsigned char SetPolicy); + unsigned char DependencyState(DepIterator const &D); + unsigned char VersionState(DepIterator D,unsigned char const Check, + unsigned char const SetMin, + unsigned char const SetPolicy) const; // Recalculates various portions of the cache, call after changing something void Update(DepIterator Dep); // Mostly internal @@ -362,7 +363,7 @@ class pkgDepCache : protected pkgCache::Namespace // Policy implementation inline VerIterator GetCandidateVer(PkgIterator const &Pkg) {return LocalPolicy->GetCandidateVer(Pkg);}; - inline bool IsImportantDep(DepIterator Dep) {return LocalPolicy->IsImportantDep(Dep);}; + inline bool IsImportantDep(DepIterator Dep) const {return LocalPolicy->IsImportantDep(Dep);}; inline Policy &GetPolicy() {return *LocalPolicy;}; // Accessors @@ -471,8 +472,8 @@ class pkgDepCache : protected pkgCache::Namespace unsigned long Depth = 0, bool FromUser = true); // read persistent states - bool readStateFile(OpProgress *prog); - bool writeStateFile(OpProgress *prog, bool InstalledOnly=true); + bool readStateFile(OpProgress * const prog); + bool writeStateFile(OpProgress * const prog, bool const InstalledOnly=true); // Size queries inline signed long long UsrSize() {return iUsrSize;}; @@ -484,11 +485,11 @@ class pkgDepCache : protected pkgCache::Namespace inline unsigned long PolicyBrokenCount() {return iPolicyBrokenCount;}; inline unsigned long BadCount() {return iBadCount;}; - bool Init(OpProgress *Prog); + bool Init(OpProgress * const Prog); // Generate all state information - void Update(OpProgress *Prog = 0); + void Update(OpProgress * const Prog = 0); - pkgDepCache(pkgCache *Cache,Policy *Plcy = 0); + pkgDepCache(pkgCache * const Cache,Policy * const Plcy = 0); virtual ~pkgDepCache(); protected: @@ -503,6 +504,8 @@ class pkgDepCache : protected pkgCache::Namespace bool const rPurge, unsigned long const Depth, bool const FromUser); private: + void * const d; + APT_HIDDEN bool IsModeChangeOk(ModeList const mode, PkgIterator const &Pkg, unsigned long const Depth, bool const FromUser); }; diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index 3c6a7e30f..aea6f3a5d 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -7,31 +7,25 @@ // Include Files /*{{{*/ #include <config.h> -#include <apt-pkg/edsp.h> #include <apt-pkg/error.h> #include <apt-pkg/cacheset.h> -#include <apt-pkg/configuration.h> -#include <apt-pkg/tagfile.h> -#include <apt-pkg/fileutl.h> -#include <apt-pkg/progress.h> #include <apt-pkg/depcache.h> #include <apt-pkg/pkgcache.h> #include <apt-pkg/cacheiterators.h> +#include <apt-pkg/progress.h> +#include <apt-pkg/fileutl.h> +#include <apt-pkg/edsp.h> +#include <apt-pkg/tagfile.h> #include <apt-pkg/strutl.h> -#include <apt-pkg/pkgrecords.h> #include <ctype.h> #include <stddef.h> #include <string.h> -#include <time.h> #include <unistd.h> #include <stdio.h> -#include <algorithm> #include <iostream> -#include <vector> #include <limits> #include <string> -#include <list> #include <apti18n.h> /*}}}*/ @@ -39,71 +33,19 @@ using std::string; // we could use pkgCache::DepType and ::Priority, but these would be localized strings… -const char * const EDSP::PrioMap[] = {0, "important", "required", "standard", +const char * const PrioMap[] = {0, "important", "required", "standard", "optional", "extra"}; -const char * const EDSP::DepMap[] = {"", "Depends", "Pre-Depends", "Suggests", +const char * const DepMap[] = {"", "Depends", "Pre-Depends", "Suggests", "Recommends" , "Conflicts", "Replaces", "Obsoletes", "Breaks", "Enhances"}; -// EDSP::WriteScenario - to the given file descriptor /*{{{*/ -bool EDSP::WriteScenario(pkgDepCache &Cache, FILE* output, OpProgress *Progress) -{ - if (Progress != NULL) - Progress->SubProgress(Cache.Head().VersionCount, _("Send scenario to solver")); - unsigned long p = 0; - std::vector<std::string> archs = APT::Configuration::getArchitectures(); - for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg) - { - std::string const arch = Pkg.Arch(); - if (std::find(archs.begin(), archs.end(), arch) == archs.end()) - continue; - for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver, ++p) - { - WriteScenarioVersion(Cache, output, Pkg, Ver); - WriteScenarioDependency(output, Ver); - fprintf(output, "\n"); - if (Progress != NULL && p % 100 == 0) - Progress->Progress(p); - } - } - return true; -} - /*}}}*/ -// EDSP::WriteLimitedScenario - to the given file descriptor /*{{{*/ -bool EDSP::WriteLimitedScenario(pkgDepCache &Cache, FILE* output, - APT::PackageSet const &pkgset, - OpProgress *Progress) -{ - if (Progress != NULL) - Progress->SubProgress(Cache.Head().VersionCount, _("Send scenario to solver")); - unsigned long p = 0; - for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg, ++p) - for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver) - { - WriteScenarioVersion(Cache, output, Pkg, Ver); - WriteScenarioLimitedDependency(output, Ver, pkgset); - fprintf(output, "\n"); - if (Progress != NULL && p % 100 == 0) - Progress->Progress(p); - } - if (Progress != NULL) - Progress->Done(); - return true; -} - /*}}}*/ -// EDSP::WriteScenarioVersion /*{{{*/ -void EDSP::WriteScenarioVersion(pkgDepCache &Cache, FILE* output, pkgCache::PkgIterator const &Pkg, + +// WriteScenarioVersion /*{{{*/ +static void WriteScenarioVersion(pkgDepCache &Cache, FILE* output, pkgCache::PkgIterator const &Pkg, pkgCache::VerIterator const &Ver) { fprintf(output, "Package: %s\n", Pkg.Name()); -#if APT_PKG_ABI >= 413 fprintf(output, "Source: %s\n", Ver.SourcePkgName()); -#else - pkgRecords Recs(Cache); - pkgRecords::Parser &rec = Recs.Lookup(Ver.FileList()); - string srcpkg = rec.SourcePkg().empty() ? Pkg.Name() : rec.SourcePkg(); - fprintf(output, "Source: %s\n", srcpkg.c_str()); -#endif fprintf(output, "Architecture: %s\n", Ver.Arch()); fprintf(output, "Version: %s\n", Ver.VerStr()); if (Pkg.CurrentVer() == Ver) @@ -129,7 +71,7 @@ void EDSP::WriteScenarioVersion(pkgDepCache &Cache, FILE* output, pkgCache::PkgI signed short const p = Cache.GetPolicy().GetPriority(File); if (Pin < p) Pin = p; - if ((File->Flags & pkgCache::Flag::NotSource) != pkgCache::Flag::NotSource) { + if (File.Flagged(pkgCache::Flag::NotSource) == false) { string Release = File.RelStr(); if (!Release.empty()) Releases.insert(Release); @@ -147,18 +89,18 @@ void EDSP::WriteScenarioVersion(pkgDepCache &Cache, FILE* output, pkgCache::PkgI fprintf(output, "APT-Automatic: yes\n"); } /*}}}*/ -// EDSP::WriteScenarioDependency /*{{{*/ -void EDSP::WriteScenarioDependency( FILE* output, pkgCache::VerIterator const &Ver) +// WriteScenarioDependency /*{{{*/ +static void WriteScenarioDependency( FILE* output, pkgCache::VerIterator const &Ver) { std::string dependencies[pkgCache::Dep::Enhances + 1]; bool orGroup = false; for (pkgCache::DepIterator Dep = Ver.DependsList(); Dep.end() == false; ++Dep) { - if (Dep.IsMultiArchImplicit() == true) + if (Dep.IsImplicit() == true) continue; if (orGroup == false) dependencies[Dep->Type].append(", "); - dependencies[Dep->Type].append(Dep.TargetPkg().Name()); + dependencies[Dep->Type].append(Dep.TargetPkg().FullName((Dep->CompareOp & pkgCache::Dep::ArchSpecific) != pkgCache::Dep::ArchSpecific)); if (Dep->Version != 0) dependencies[Dep->Type].append(" (").append(pkgCache::CompTypeDeb(Dep->CompareOp)).append(" ").append(Dep.TargetVer()).append(")"); if ((Dep->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or) @@ -183,8 +125,8 @@ void EDSP::WriteScenarioDependency( FILE* output, pkgCache::VerIterator const &V fprintf(output, "Provides: %s\n", provides.c_str()+2); } /*}}}*/ -// EDSP::WriteScenarioLimitedDependency /*{{{*/ -void EDSP::WriteScenarioLimitedDependency(FILE* output, +// WriteScenarioLimitedDependency /*{{{*/ +static void WriteScenarioLimitedDependency(FILE* output, pkgCache::VerIterator const &Ver, APT::PackageSet const &pkgset) { @@ -192,7 +134,7 @@ void EDSP::WriteScenarioLimitedDependency(FILE* output, bool orGroup = false; for (pkgCache::DepIterator Dep = Ver.DependsList(); Dep.end() == false; ++Dep) { - if (Dep.IsMultiArchImplicit() == true) + if (Dep.IsImplicit() == true) continue; if (orGroup == false) { @@ -208,7 +150,7 @@ void EDSP::WriteScenarioLimitedDependency(FILE* output, orGroup = false; continue; } - dependencies[Dep->Type].append(Dep.TargetPkg().Name()); + dependencies[Dep->Type].append(Dep.TargetPkg().FullName((Dep->CompareOp & pkgCache::Dep::ArchSpecific) != pkgCache::Dep::ArchSpecific)); if (Dep->Version != 0) dependencies[Dep->Type].append(" (").append(pkgCache::CompTypeDeb(Dep->CompareOp)).append(" ").append(Dep.TargetVer()).append(")"); if ((Dep->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or) @@ -235,6 +177,52 @@ void EDSP::WriteScenarioLimitedDependency(FILE* output, fprintf(output, "Provides: %s\n", provides.c_str()+2); } /*}}}*/ +// EDSP::WriteScenario - to the given file descriptor /*{{{*/ +bool EDSP::WriteScenario(pkgDepCache &Cache, FILE* output, OpProgress *Progress) +{ + if (Progress != NULL) + Progress->SubProgress(Cache.Head().VersionCount, _("Send scenario to solver")); + unsigned long p = 0; + std::vector<std::string> archs = APT::Configuration::getArchitectures(); + for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg) + { + std::string const arch = Pkg.Arch(); + if (std::find(archs.begin(), archs.end(), arch) == archs.end()) + continue; + for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver, ++p) + { + WriteScenarioVersion(Cache, output, Pkg, Ver); + WriteScenarioDependency(output, Ver); + fprintf(output, "\n"); + if (Progress != NULL && p % 100 == 0) + Progress->Progress(p); + } + } + return true; +} + /*}}}*/ +// EDSP::WriteLimitedScenario - to the given file descriptor /*{{{*/ +bool EDSP::WriteLimitedScenario(pkgDepCache &Cache, FILE* output, + APT::PackageSet const &pkgset, + OpProgress *Progress) +{ + if (Progress != NULL) + Progress->SubProgress(Cache.Head().VersionCount, _("Send scenario to solver")); + unsigned long p = 0; + for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg, ++p) + for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver) + { + WriteScenarioVersion(Cache, output, Pkg, Ver); + WriteScenarioLimitedDependency(output, Ver, pkgset); + fprintf(output, "\n"); + if (Progress != NULL && p % 100 == 0) + Progress->Progress(p); + } + if (Progress != NULL) + Progress->Done(); + return true; +} + /*}}}*/ // EDSP::WriteRequest - to the given file descriptor /*{{{*/ bool EDSP::WriteRequest(pkgDepCache &Cache, FILE* output, bool const Upgrade, bool const DistUpgrade, bool const AutoRemove, @@ -365,13 +353,13 @@ bool EDSP::ReadResponse(int const input, pkgDepCache &Cache, OpProgress *Progres return true; } /*}}}*/ -// EDSP::ReadLine - first line from the given file descriptor /*{{{*/ +// ReadLine - first line from the given file descriptor /*{{{*/ // --------------------------------------------------------------------- /* Little helper method to read a complete line into a string. Similar to fgets but we need to use the low-level read() here as otherwise the listparser will be confused later on as mixing of fgets and read isn't a supported action according to the manpages and results are undefined */ -bool EDSP::ReadLine(int const input, std::string &line) { +static bool ReadLine(int const input, std::string &line) { char one; ssize_t data = 0; line.erase(); @@ -390,11 +378,11 @@ bool EDSP::ReadLine(int const input, std::string &line) { return false; } /*}}}*/ -// EDSP::StringToBool - convert yes/no to bool /*{{{*/ +// StringToBool - convert yes/no to bool /*{{{*/ // --------------------------------------------------------------------- /* we are not as lazy as we are in the global StringToBool as we really only accept yes/no here - but we will ignore leading spaces */ -bool EDSP::StringToBool(char const *answer, bool const defValue) { +static bool StringToBool(char const *answer, bool const defValue) { for (; isspace(*answer) != 0; ++answer); if (strncasecmp(answer, "yes", 3) == 0) return true; @@ -443,11 +431,11 @@ bool EDSP::ReadRequest(int const input, std::list<std::string> &install, request = &remove; } else if (line.compare(0, 8, "Upgrade:") == 0) - upgrade = EDSP::StringToBool(line.c_str() + 9, false); + upgrade = StringToBool(line.c_str() + 9, false); else if (line.compare(0, 13, "Dist-Upgrade:") == 0) - distUpgrade = EDSP::StringToBool(line.c_str() + 14, false); + distUpgrade = StringToBool(line.c_str() + 14, false); else if (line.compare(0, 11, "Autoremove:") == 0) - autoRemove = EDSP::StringToBool(line.c_str() + 12, false); + autoRemove = StringToBool(line.c_str() + 12, false); else if (line.compare(0, 13, "Architecture:") == 0) _config->Set("APT::Architecture", line.c_str() + 14); else if (line.compare(0, 14, "Architectures:") == 0) diff --git a/apt-pkg/edsp.h b/apt-pkg/edsp.h index 9e833556a..4f5f500a1 100644 --- a/apt-pkg/edsp.h +++ b/apt-pkg/edsp.h @@ -27,24 +27,8 @@ class pkgDepCache; class OpProgress; -class EDSP /*{{{*/ +namespace EDSP /*{{{*/ { - // we could use pkgCache::DepType and ::Priority, but these would be localized strings… - static const char * const PrioMap[]; - static const char * const DepMap[]; - - APT_HIDDEN bool static ReadLine(int const input, std::string &line); - APT_HIDDEN bool static StringToBool(char const *answer, bool const defValue); - - APT_HIDDEN void static WriteScenarioVersion(pkgDepCache &Cache, FILE* output, - pkgCache::PkgIterator const &Pkg, - pkgCache::VerIterator const &Ver); - APT_HIDDEN void static WriteScenarioDependency(FILE* output, - pkgCache::VerIterator const &Ver); - APT_HIDDEN void static WriteScenarioLimitedDependency(FILE* output, - pkgCache::VerIterator const &Ver, - APT::PackageSet const &pkgset); -public: /** \brief creates the EDSP request stanza * * In the EDSP protocol the first thing send to the resolver is a stanza @@ -61,7 +45,7 @@ public: * * \return true if request was composed successfully, otherwise false */ - bool static WriteRequest(pkgDepCache &Cache, FILE* output, + bool WriteRequest(pkgDepCache &Cache, FILE* output, bool const upgrade = false, bool const distUpgrade = false, bool const autoRemove = false, @@ -84,7 +68,7 @@ public: * * \return true if universe was composed successfully, otherwise false */ - bool static WriteScenario(pkgDepCache &Cache, FILE* output, OpProgress *Progress = NULL); + bool WriteScenario(pkgDepCache &Cache, FILE* output, OpProgress *Progress = NULL); /** \brief creates a limited scenario representing the package universe * @@ -101,7 +85,7 @@ public: * * \return true if universe was composed successfully, otherwise false */ - bool static WriteLimitedScenario(pkgDepCache &Cache, FILE* output, + bool WriteLimitedScenario(pkgDepCache &Cache, FILE* output, APT::PackageSet const &pkgset, OpProgress *Progress = NULL); @@ -118,7 +102,7 @@ public: * * \return true if a solution is found and applied correctly, otherwise false */ - bool static ReadResponse(int const input, pkgDepCache &Cache, OpProgress *Progress = NULL); + bool ReadResponse(int const input, pkgDepCache &Cache, OpProgress *Progress = NULL); /** \brief search and read the request stanza for action later * @@ -136,7 +120,7 @@ public: * * \return true if the request could be found and worked on, otherwise false */ - bool static ReadRequest(int const input, std::list<std::string> &install, + bool ReadRequest(int const input, std::list<std::string> &install, std::list<std::string> &remove, bool &upgrade, bool &distUpgrade, bool &autoRemove); @@ -152,7 +136,7 @@ public: * * \return false if the request couldn't be applied, true otherwise */ - bool static ApplyRequest(std::list<std::string> const &install, + bool ApplyRequest(std::list<std::string> const &install, std::list<std::string> const &remove, pkgDepCache &Cache); @@ -168,7 +152,7 @@ public: * * \return true if solution could be written, otherwise false */ - bool static WriteSolution(pkgDepCache &Cache, FILE* output); + bool WriteSolution(pkgDepCache &Cache, FILE* output); /** \brief sends a progress report * @@ -176,7 +160,7 @@ public: * \param message the solver wants the user to see * \param output the front-end listens for progress report */ - bool static WriteProgress(unsigned short const percent, const char* const message, FILE* output); + bool WriteProgress(unsigned short const percent, const char* const message, FILE* output); /** \brief sends an error report * @@ -193,7 +177,7 @@ public: * \param message is free form text to describe the error * \param output the front-end listens for error messages */ - bool static WriteError(char const * const uuid, std::string const &message, FILE* output); + bool WriteError(char const * const uuid, std::string const &message, FILE* output); /** \brief executes the given solver and returns the pipe ends @@ -207,8 +191,8 @@ public: * * \return PID of the started solver or 0 if failure occurred */ - pid_t static ExecuteSolver(const char* const solver, int * const solver_in, int * const solver_out, bool /*overload*/); - APT_DEPRECATED bool static ExecuteSolver(const char* const solver, int *solver_in, int *solver_out); + pid_t ExecuteSolver(const char* const solver, int * const solver_in, int * const solver_out, bool /*overload*/); + APT_DEPRECATED bool ExecuteSolver(const char* const solver, int *solver_in, int *solver_out); /** \brief call an external resolver to handle the request * @@ -224,9 +208,9 @@ public: * \return true if the solver has successfully solved the problem, * otherwise false */ - bool static ResolveExternal(const char* const solver, pkgDepCache &Cache, + bool ResolveExternal(const char* const solver, pkgDepCache &Cache, bool const upgrade, bool const distUpgrade, bool const autoRemove, OpProgress *Progress = NULL); -}; +} /*}}}*/ #endif diff --git a/apt-pkg/edsp/edspindexfile.cc b/apt-pkg/edsp/edspindexfile.cc index d00536362..409117c5e 100644 --- a/apt-pkg/edsp/edspindexfile.cc +++ b/apt-pkg/edsp/edspindexfile.cc @@ -12,13 +12,8 @@ #include <apt-pkg/edsplistparser.h> #include <apt-pkg/error.h> #include <apt-pkg/fileutl.h> -#include <apt-pkg/progress.h> -#include <apt-pkg/debindexfile.h> #include <apt-pkg/indexfile.h> -#include <apt-pkg/mmap.h> #include <apt-pkg/pkgcache.h> -#include <apt-pkg/cacheiterators.h> -#include <apt-pkg/pkgcachegen.h> #include <apt-pkg/pkgrecords.h> #include <stddef.h> @@ -26,59 +21,67 @@ #include <string> /*}}}*/ -// edspIndex::edspIndex - Constructor /*{{{*/ -// --------------------------------------------------------------------- -/* */ -edspIndex::edspIndex(std::string File) : debStatusIndex(File) +// EDSP Index /*{{{*/ +edspIndex::edspIndex(std::string const &File) : pkgDebianIndexRealFile(File, true), d(NULL) { } - /*}}}*/ -// StatusIndex::Merge - Load the index file into a cache /*{{{*/ -bool edspIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const +std::string edspIndex::GetComponent() const +{ + return "edsp"; +} +std::string edspIndex::GetArchitecture() const +{ + return std::string(); +} +bool edspIndex::HasPackages() const +{ + return true; +} +bool edspIndex::Exists() const { - FileFd Pkg; - if (File != "stdin") - Pkg.Open(File, FileFd::ReadOnly); - else - Pkg.OpenDescriptor(STDIN_FILENO, FileFd::ReadOnly); - if (_error->PendingError() == true) - return false; - edspListParser Parser(&Pkg); - if (_error->PendingError() == true) - return false; - - if (Prog != NULL) - Prog->SubProgress(0,File); - if (Gen.SelectFile(File,std::string(),*this) == false) - return _error->Error("Problem with SelectFile %s",File.c_str()); - - // Store the IMS information - pkgCache::PkgFileIterator CFile = Gen.GetCurFile(); - CFile->Size = Pkg.FileSize(); - CFile->mtime = Pkg.ModificationTime(); - map_stringitem_t const storage = Gen.StoreString(pkgCacheGenerator::MIXED, "edsp::scenario"); - CFile->Archive = storage; - - if (Gen.MergeList(Parser) == false) - return _error->Error("Problem with MergeList %s",File.c_str()); return true; } +uint8_t edspIndex::GetIndexFlags() const +{ + return 0; +} +bool edspIndex::OpenListFile(FileFd &Pkg, std::string const &FileName) +{ + if (FileName.empty() == false && FileName != "stdin") + return pkgDebianIndexRealFile::OpenListFile(Pkg, FileName); + if (Pkg.OpenDescriptor(STDIN_FILENO, FileFd::ReadOnly) == false) + return _error->Error("Problem opening %s",FileName.c_str()); + return true; +} +pkgCacheListParser * edspIndex::CreateListParser(FileFd &Pkg) +{ + if (Pkg.IsOpen() == false) + return NULL; + _error->PushToStack(); + pkgCacheListParser * const Parser = new edspListParser(&Pkg); + bool const newError = _error->PendingError(); + _error->MergeWithStack(); + return newError ? NULL : Parser; +} /*}}}*/ + // Index File types for APT /*{{{*/ class APT_HIDDEN edspIFType: public pkgIndexFile::Type { public: - virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator) const + virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator const &) const APT_OVERRIDE { // we don't have a record parser for this type as the file is not presistent return NULL; }; edspIFType() {Label = "EDSP scenario file";}; }; -APT_HIDDEN edspIFType _apt_Universe; +APT_HIDDEN edspIFType _apt_Edsp; const pkgIndexFile::Type *edspIndex::GetType() const { - return &_apt_Universe; + return &_apt_Edsp; } /*}}}*/ + +edspIndex::~edspIndex() {} diff --git a/apt-pkg/edsp/edspindexfile.h b/apt-pkg/edsp/edspindexfile.h index 8c18d8cbd..4548bff3c 100644 --- a/apt-pkg/edsp/edspindexfile.h +++ b/apt-pkg/edsp/edspindexfile.h @@ -18,18 +18,25 @@ class OpProgress; class pkgCacheGenerator; -class APT_HIDDEN edspIndex : public debStatusIndex +class APT_HIDDEN edspIndex : public pkgDebianIndexRealFile { /** \brief dpointer placeholder (for later in case we need it) */ - void *d; - - public: - - virtual const Type *GetType() const APT_CONST; - - virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const; - - edspIndex(std::string File); + void * const d; + +protected: + APT_HIDDEN virtual pkgCacheListParser * CreateListParser(FileFd &Pkg) APT_OVERRIDE; + virtual bool OpenListFile(FileFd &Pkg, std::string const &File) APT_OVERRIDE; + virtual uint8_t GetIndexFlags() const APT_OVERRIDE; + virtual std::string GetComponent() const APT_OVERRIDE; + virtual std::string GetArchitecture() const APT_OVERRIDE; +public: + + virtual const Type *GetType() const APT_OVERRIDE APT_CONST; + virtual bool Exists() const APT_OVERRIDE; + virtual bool HasPackages() const APT_OVERRIDE; + + edspIndex(std::string const &File); + virtual ~edspIndex(); }; #endif diff --git a/apt-pkg/edsp/edsplistparser.cc b/apt-pkg/edsp/edsplistparser.cc index 212dc7840..ff79b537e 100644 --- a/apt-pkg/edsp/edsplistparser.cc +++ b/apt-pkg/edsp/edsplistparser.cc @@ -18,11 +18,10 @@ #include <apt-pkg/cacheiterators.h> #include <apt-pkg/tagfile.h> -#include <string> /*}}}*/ // ListParser::edspListParser - Constructor /*{{{*/ -edspListParser::edspListParser(FileFd *File, std::string const &Arch) : debListParser(File, Arch) +edspListParser::edspListParser(FileFd *File) : debListParser(File), d(NULL) {} /*}}}*/ // ListParser::NewVersion - Fill in the version structure /*{{{*/ @@ -86,9 +85,11 @@ bool edspListParser::ParseStatus(pkgCache::PkgIterator &Pkg, } /*}}}*/ // ListParser::LoadReleaseInfo - Load the release information /*{{{*/ -APT_CONST bool edspListParser::LoadReleaseInfo(pkgCache::PkgFileIterator & /*FileI*/, - FileFd & /*File*/, std::string /*component*/) +APT_CONST bool edspListParser::LoadReleaseInfo(pkgCache::RlsFileIterator & /*FileI*/, + FileFd & /*File*/, std::string const &/*component*/) { return true; } /*}}}*/ + +edspListParser::~edspListParser() {} diff --git a/apt-pkg/edsp/edsplistparser.h b/apt-pkg/edsp/edsplistparser.h index 86cd77606..221229302 100644 --- a/apt-pkg/edsp/edsplistparser.h +++ b/apt-pkg/edsp/edsplistparser.h @@ -27,20 +27,22 @@ class FileFd; class APT_HIDDEN edspListParser : public debListParser { + void * const d; public: - virtual bool NewVersion(pkgCache::VerIterator &Ver); + virtual bool NewVersion(pkgCache::VerIterator &Ver) APT_OVERRIDE; virtual std::string Description(); virtual std::string DescriptionLanguage(); - virtual MD5SumValue Description_md5(); - virtual unsigned short VersionHash(); + virtual MD5SumValue Description_md5() APT_OVERRIDE; + virtual unsigned short VersionHash() APT_OVERRIDE; - bool LoadReleaseInfo(pkgCache::PkgFileIterator &FileI,FileFd &File, - std::string section); + bool LoadReleaseInfo(pkgCache::RlsFileIterator &FileI,FileFd &File, + std::string const §ion); - edspListParser(FileFd *File, std::string const &Arch = ""); + edspListParser(FileFd *File); + virtual ~edspListParser(); protected: - virtual bool ParseStatus(pkgCache::PkgIterator &Pkg,pkgCache::VerIterator &Ver); + virtual bool ParseStatus(pkgCache::PkgIterator &Pkg,pkgCache::VerIterator &Ver) APT_OVERRIDE; }; diff --git a/apt-pkg/edsp/edspsystem.cc b/apt-pkg/edsp/edspsystem.cc index 063517421..f577efcbd 100644 --- a/apt-pkg/edsp/edspsystem.cc +++ b/apt-pkg/edsp/edspsystem.cc @@ -15,7 +15,6 @@ #include <apt-pkg/debversion.h> #include <apt-pkg/edspindexfile.h> #include <apt-pkg/edspsystem.h> -#include <apt-pkg/fileutl.h> #include <apt-pkg/pkgcache.h> #include <apt-pkg/cacheiterators.h> @@ -23,16 +22,11 @@ #include <string> #include <vector> -#include <apti18n.h> /*}}}*/ -// System::debSystem - Constructor /*{{{*/ -edspSystem::edspSystem() +// System::edspSystem - Constructor /*{{{*/ +edspSystem::edspSystem() : pkgSystem("Debian APT solver interface", &debVS), d(NULL), StatusFile(NULL) { - StatusFile = 0; - - Label = "Debian APT solver interface"; - VS = &debVS; } /*}}}*/ // System::~debSystem - Destructor /*{{{*/ @@ -85,18 +79,13 @@ bool edspSystem::ArchiveSupported(const char * /*Type*/) return false; } /*}}}*/ -// System::Score - Determine if we should use the edsp system /*{{{*/ -signed edspSystem::Score(Configuration const &Cnf) +// System::Score - Never use the EDSP system automatically /*{{{*/ +signed edspSystem::Score(Configuration const &) { - if (Cnf.Find("edsp::scenario", "") == "stdin") - return 1000; - if (RealFileExists(Cnf.FindFile("edsp::scenario","")) == true) - return 1000; return -1000; } /*}}}*/ -// System::AddStatusFiles - Register the status files /*{{{*/ -bool edspSystem::AddStatusFiles(std::vector<pkgIndexFile *> &List) +bool edspSystem::AddStatusFiles(std::vector<pkgIndexFile *> &List) /*{{{*/ { if (StatusFile == 0) { diff --git a/apt-pkg/edsp/edspsystem.h b/apt-pkg/edsp/edspsystem.h index 06a63f40c..ec42bef75 100644 --- a/apt-pkg/edsp/edspsystem.h +++ b/apt-pkg/edsp/edspsystem.h @@ -16,6 +16,8 @@ #include <vector> +#include <apt-pkg/macros.h> + class Configuration; class pkgDepCache; class pkgIndexFile; @@ -25,24 +27,24 @@ class edspIndex; class APT_HIDDEN edspSystem : public pkgSystem { /** \brief dpointer placeholder (for later in case we need it) */ - void *d; + void * const d; edspIndex *StatusFile; public: - virtual bool Lock() APT_CONST; - virtual bool UnLock(bool NoErrors = false) APT_CONST; - virtual pkgPackageManager *CreatePM(pkgDepCache *Cache) const APT_CONST; - virtual bool Initialize(Configuration &Cnf); - virtual bool ArchiveSupported(const char *Type) APT_CONST; - virtual signed Score(Configuration const &Cnf); - virtual bool AddStatusFiles(std::vector<pkgIndexFile *> &List); + virtual bool Lock() APT_OVERRIDE APT_CONST; + virtual bool UnLock(bool NoErrors = false) APT_OVERRIDE APT_CONST; + virtual pkgPackageManager *CreatePM(pkgDepCache *Cache) const APT_OVERRIDE APT_CONST; + virtual bool Initialize(Configuration &Cnf) APT_OVERRIDE; + virtual bool ArchiveSupported(const char *Type) APT_OVERRIDE APT_CONST; + virtual signed Score(Configuration const &Cnf) APT_OVERRIDE; + virtual bool AddStatusFiles(std::vector<pkgIndexFile *> &List) APT_OVERRIDE; virtual bool FindIndex(pkgCache::PkgFileIterator File, - pkgIndexFile *&Found) const; + pkgIndexFile *&Found) const APT_OVERRIDE; edspSystem(); - ~edspSystem(); + virtual ~edspSystem(); }; #endif diff --git a/apt-pkg/indexcopy.cc b/apt-pkg/indexcopy.cc index 461aa4217..8a7df2eb3 100644 --- a/apt-pkg/indexcopy.cc +++ b/apt-pkg/indexcopy.cc @@ -19,18 +19,19 @@ #include <apt-pkg/aptconfiguration.h> #include <apt-pkg/configuration.h> #include <apt-pkg/tagfile.h> -#include <apt-pkg/indexrecords.h> +#include <apt-pkg/metaindex.h> #include <apt-pkg/cdrom.h> #include <apt-pkg/gpgv.h> #include <apt-pkg/hashes.h> +#include <apt-pkg/debmetaindex.h> #include <iostream> -#include <sstream> #include <unistd.h> #include <sys/stat.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <sstream> #include "indexcopy.h" #include <apti18n.h> @@ -424,7 +425,6 @@ bool PackageCopy::GetFile(string &File,unsigned long long &Size) // PackageCopy::RewriteEntry - Rewrite the entry with a new filename /*{{{*/ bool PackageCopy::RewriteEntry(FileFd &Target,string const &File) { - string const Dir(File,0,File.rfind('/')); std::vector<pkgTagSection::Tag> Changes; Changes.push_back(pkgTagSection::Tag::Rewrite("Filename", File)); @@ -477,9 +477,9 @@ bool SourceCopy::RewriteEntry(FileFd &Target, std::string const &File) } /*}}}*/ // SigVerify::Verify - Verify a files md5sum against its metaindex /*{{{*/ -bool SigVerify::Verify(string prefix, string file, indexRecords *MetaIndex) +bool SigVerify::Verify(string prefix, string file, metaIndex *MetaIndex) { - const indexRecords::checkSum *Record = MetaIndex->Lookup(file); + const metaIndex::checkSum *Record = MetaIndex->Lookup(file); bool const Debug = _config->FindB("Debug::aptcdrom",false); // we skip non-existing files in the verifcation of the Release file @@ -546,11 +546,11 @@ bool SigVerify::CopyAndVerify(string CDROM,string Name,vector<string> &SigList, // Read all Release files for (vector<string>::iterator I = SigList.begin(); I != SigList.end(); ++I) - { + { if(Debug) cout << "Signature verify for: " << *I << endl; - indexRecords *MetaIndex = new indexRecords; + metaIndex *MetaIndex = new debReleaseIndex("",""); string prefix = *I; string const releasegpg = *I+"Release.gpg"; @@ -592,12 +592,13 @@ bool SigVerify::CopyAndVerify(string CDROM,string Name,vector<string> &SigList, } // Open the Release file and add it to the MetaIndex - if(!MetaIndex->Load(release)) + std::string ErrorText; + if(MetaIndex->Load(release, &ErrorText) == false) { - _error->Error("%s",MetaIndex->ErrorText.c_str()); + _error->Error("%s", ErrorText.c_str()); return false; } - + // go over the Indexfiles and see if they verify // if so, remove them from our copy of the lists vector<string> keys = MetaIndex->MetaKeys(); @@ -770,4 +771,14 @@ bool TranslationsCopy::CopyTranslations(string CDROM,string Name, /*{{{*/ } /*}}}*/ +IndexCopy::IndexCopy() : d(NULL) {} APT_CONST IndexCopy::~IndexCopy() {} + +PackageCopy::PackageCopy() : IndexCopy(), d(NULL) {} +APT_CONST PackageCopy::~PackageCopy() {} +SourceCopy::SourceCopy() : IndexCopy(), d(NULL) {} +APT_CONST SourceCopy::~SourceCopy() {} +TranslationsCopy::TranslationsCopy() : d(NULL) {} +APT_CONST TranslationsCopy::~TranslationsCopy() {} +SigVerify::SigVerify() : d(NULL) {} +APT_CONST SigVerify::~SigVerify() {} diff --git a/apt-pkg/indexcopy.h b/apt-pkg/indexcopy.h index 729b0c8cb..d4f04b5b1 100644 --- a/apt-pkg/indexcopy.h +++ b/apt-pkg/indexcopy.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: indexcopy.h,v 1.3 2001/05/27 04:46:54 jgg Exp $ /* ###################################################################### Index Copying - Aid for copying and verifying the index files @@ -11,8 +10,10 @@ #define INDEXCOPY_H #include <vector> +#ifndef APT_11_CLEAN_HEADERS #include <string> #include <stdio.h> +#endif #include <apt-pkg/macros.h> @@ -26,14 +27,14 @@ using std::vector; #endif class pkgTagSection; -class indexRecords; class pkgCdromStatus; class FileFd; +class metaIndex; class IndexCopy /*{{{*/ { /** \brief dpointer placeholder (for later in case we need it) */ - void *d; + void * const d; protected: @@ -54,47 +55,60 @@ class IndexCopy /*{{{*/ bool CopyPackages(std::string CDROM,std::string Name,std::vector<std::string> &List, pkgCdromStatus *log); + IndexCopy(); virtual ~IndexCopy(); }; /*}}}*/ class PackageCopy : public IndexCopy /*{{{*/ { + void * const d; protected: - - virtual bool GetFile(std::string &Filename,unsigned long long &Size); - virtual bool RewriteEntry(FileFd &Target, std::string const &File); - virtual const char *GetFileName() {return "Packages";}; - virtual const char *Type() {return "Package";}; - + + virtual bool GetFile(std::string &Filename,unsigned long long &Size) APT_OVERRIDE; + virtual bool RewriteEntry(FileFd &Target, std::string const &File) APT_OVERRIDE; + virtual const char *GetFileName() APT_OVERRIDE {return "Packages";}; + virtual const char *Type() APT_OVERRIDE {return "Package";}; + + public: + PackageCopy(); + virtual ~PackageCopy(); }; /*}}}*/ class SourceCopy : public IndexCopy /*{{{*/ { + void * const d; protected: - virtual bool GetFile(std::string &Filename,unsigned long long &Size); - virtual bool RewriteEntry(FileFd &Target, std::string const &File); - virtual const char *GetFileName() {return "Sources";}; - virtual const char *Type() {return "Source";}; - + virtual bool GetFile(std::string &Filename,unsigned long long &Size) APT_OVERRIDE; + virtual bool RewriteEntry(FileFd &Target, std::string const &File) APT_OVERRIDE; + virtual const char *GetFileName() APT_OVERRIDE {return "Sources";}; + virtual const char *Type() APT_OVERRIDE {return "Source";}; + + public: + SourceCopy(); + virtual ~SourceCopy(); }; /*}}}*/ class TranslationsCopy /*{{{*/ { + void * const d; protected: pkgTagSection *Section; public: bool CopyTranslations(std::string CDROM,std::string Name,std::vector<std::string> &List, pkgCdromStatus *log); + + TranslationsCopy(); + virtual ~TranslationsCopy(); }; /*}}}*/ class SigVerify /*{{{*/ { /** \brief dpointer placeholder (for later in case we need it) */ - void *d; + void * const d; - APT_HIDDEN bool Verify(std::string prefix,std::string file, indexRecords *records); + APT_HIDDEN bool Verify(std::string prefix,std::string file, metaIndex *records); APT_HIDDEN bool CopyMetaIndex(std::string CDROM, std::string CDName, std::string prefix, std::string file); @@ -106,6 +120,9 @@ class SigVerify /*{{{*/ int const &statusfd, int fd[2]); APT_DEPRECATED static bool RunGPGV(std::string const &File, std::string const &FileOut, int const &statusfd = -1); + + SigVerify(); + virtual ~SigVerify(); }; /*}}}*/ diff --git a/apt-pkg/indexfile.cc b/apt-pkg/indexfile.cc index 89615cb41..8e50ecfae 100644 --- a/apt-pkg/indexfile.cc +++ b/apt-pkg/indexfile.cc @@ -10,18 +10,27 @@ // Include Files /*{{{*/ #include<config.h> +#include <apt-pkg/configuration.h> #include <apt-pkg/indexfile.h> #include <apt-pkg/error.h> +#include <apt-pkg/fileutl.h> #include <apt-pkg/aptconfiguration.h> #include <apt-pkg/pkgcache.h> +#include <apt-pkg/pkgcachegen.h> #include <apt-pkg/cacheiterators.h> #include <apt-pkg/srcrecords.h> +#include <apt-pkg/progress.h> #include <apt-pkg/macros.h> +#include <apt-pkg/deblistparser.h> + +#include <sys/stat.h> + #include <string> #include <vector> #include <clocale> #include <cstring> +#include <memory> /*}}}*/ // Global list of Item supported @@ -50,25 +59,24 @@ pkgIndexFile::Type *pkgIndexFile::Type::GetType(const char *Type) return 0; } /*}}}*/ +pkgIndexFile::pkgIndexFile(bool const Trusted) : /*{{{*/ + d(NULL), Trusted(Trusted) +{ +} + /*}}}*/ // IndexFile::ArchiveInfo - Stub /*{{{*/ -// --------------------------------------------------------------------- -/* */ -std::string pkgIndexFile::ArchiveInfo(pkgCache::VerIterator /*Ver*/) const +std::string pkgIndexFile::ArchiveInfo(pkgCache::VerIterator const &/*Ver*/) const { return std::string(); } /*}}}*/ // IndexFile::FindInCache - Stub /*{{{*/ -// --------------------------------------------------------------------- -/* */ pkgCache::PkgFileIterator pkgIndexFile::FindInCache(pkgCache &Cache) const { return pkgCache::PkgFileIterator(Cache); } /*}}}*/ // IndexFile::SourceIndex - Stub /*{{{*/ -// --------------------------------------------------------------------- -/* */ std::string pkgIndexFile::SourceInfo(pkgSrcRecords::Parser const &/*Record*/, pkgSrcRecords::File const &/*File*/) const { @@ -88,7 +96,7 @@ bool pkgIndexFile::TranslationsAvailable() { is already done in getLanguages(). Note also that this check is rather bad (doesn't take three character like ast into account). TODO: Remove method with next API break */ -APT_DEPRECATED bool pkgIndexFile::CheckLanguageCode(const char *Lang) +APT_DEPRECATED bool pkgIndexFile::CheckLanguageCode(const char * const Lang) { if (strlen(Lang) == 2 || (strlen(Lang) == 5 && Lang[2] == '_')) return true; @@ -110,3 +118,267 @@ APT_DEPRECATED std::string pkgIndexFile::LanguageCode() { return APT::Configuration::getLanguages()[0]; } /*}}}*/ + +// IndexTarget - Constructor /*{{{*/ +IndexTarget::IndexTarget(std::string const &MetaKey, std::string const &ShortDesc, + std::string const &LongDesc, std::string const &URI, bool const IsOptional, + bool const KeepCompressed, std::map<std::string, std::string> const &Options) : + URI(URI), Description(LongDesc), ShortDesc(ShortDesc), MetaKey(MetaKey), + IsOptional(IsOptional), KeepCompressed(KeepCompressed), Options(Options) +{ +} + /*}}}*/ +std::string IndexTarget::Option(OptionKeys const EnumKey) const /*{{{*/ +{ + std::string Key; + switch (EnumKey) + { +#define APT_CASE(X) case X: Key = #X; break + APT_CASE(SITE); + APT_CASE(RELEASE); + APT_CASE(COMPONENT); + APT_CASE(LANGUAGE); + APT_CASE(ARCHITECTURE); + APT_CASE(BASE_URI); + APT_CASE(REPO_URI); + APT_CASE(TARGET_OF); + APT_CASE(CREATED_BY); +#undef APT_CASE + case FILENAME: return _config->FindDir("Dir::State::lists") + URItoFileName(URI); + case EXISTING_FILENAME: + std::string const filename = Option(FILENAME); + std::vector<std::string> const types = APT::Configuration::getCompressionTypes(); + for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t) + { + if (t->empty()) + continue; + std::string const file = (*t == "uncompressed") ? filename : (filename + "." + *t); + if (FileExists(file)) + return file; + } + return ""; + } + std::map<std::string,std::string>::const_iterator const M = Options.find(Key); + if (M == Options.end()) + return ""; + return M->second; +} + /*}}}*/ +std::string IndexTarget::Format(std::string format) const /*{{{*/ +{ + for (std::map<std::string, std::string>::const_iterator O = Options.begin(); O != Options.end(); ++O) + { + format = SubstVar(format, std::string("$(") + O->first + ")", O->second); + } + format = SubstVar(format, "$(METAKEY)", MetaKey); + format = SubstVar(format, "$(SHORTDESC)", ShortDesc); + format = SubstVar(format, "$(DESCRIPTION)", Description); + format = SubstVar(format, "$(URI)", URI); + format = SubstVar(format, "$(FILENAME)", Option(IndexTarget::FILENAME)); + return format; +} + /*}}}*/ + +pkgDebianIndexTargetFile::pkgDebianIndexTargetFile(IndexTarget const &Target, bool const Trusted) :/*{{{*/ + pkgDebianIndexFile(Trusted), d(NULL), Target(Target) +{ +} + /*}}}*/ +std::string pkgDebianIndexTargetFile::ArchiveURI(std::string const &File) const/*{{{*/ +{ + return Target.Option(IndexTarget::REPO_URI) + File; +} + /*}}}*/ +std::string pkgDebianIndexTargetFile::Describe(bool const Short) const /*{{{*/ +{ + if (Short) + return Target.Description; + return Target.Description + " (" + IndexFileName() + ")"; +} + /*}}}*/ +std::string pkgDebianIndexTargetFile::IndexFileName() const /*{{{*/ +{ + std::string const s = Target.Option(IndexTarget::FILENAME); + if (FileExists(s)) + return s; + + std::vector<std::string> types = APT::Configuration::getCompressionTypes(); + for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t) + { + std::string p = s + '.' + *t; + if (FileExists(p)) + return p; + } + return s; +} + /*}}}*/ +unsigned long pkgDebianIndexTargetFile::Size() const /*{{{*/ +{ + unsigned long size = 0; + + /* we need to ignore errors here; if the lists are absent, just return 0 */ + _error->PushToStack(); + + FileFd f(IndexFileName(), FileFd::ReadOnly, FileFd::Extension); + if (!f.Failed()) + size = f.Size(); + + if (_error->PendingError() == true) + size = 0; + _error->RevertToStack(); + + return size; +} + /*}}}*/ +bool pkgDebianIndexTargetFile::Exists() const /*{{{*/ +{ + return FileExists(IndexFileName()); +} + /*}}}*/ +std::string pkgDebianIndexTargetFile::GetArchitecture() const /*{{{*/ +{ + return Target.Option(IndexTarget::ARCHITECTURE); +} + /*}}}*/ +std::string pkgDebianIndexTargetFile::GetComponent() const /*{{{*/ +{ + return Target.Option(IndexTarget::COMPONENT); +} + /*}}}*/ +bool pkgDebianIndexTargetFile::OpenListFile(FileFd &Pkg, std::string const &FileName)/*{{{*/ +{ + if (Pkg.Open(FileName, FileFd::ReadOnly, FileFd::Extension) == false) + return _error->Error("Problem opening %s",FileName.c_str()); + return true; +} + /*}}}*/ +std::string pkgDebianIndexTargetFile::GetProgressDescription() const +{ + return Target.Description; +} + +pkgDebianIndexRealFile::pkgDebianIndexRealFile(std::string const &File, bool const Trusted) :/*{{{*/ + pkgDebianIndexFile(Trusted), d(NULL), File(flAbsPath(File)) +{ +} + /*}}}*/ +// IndexRealFile::Size - Return the size of the index /*{{{*/ +unsigned long pkgDebianIndexRealFile::Size() const +{ + struct stat S; + if (stat(File.c_str(),&S) != 0) + return 0; + return S.st_size; +} + /*}}}*/ +bool pkgDebianIndexRealFile::Exists() const /*{{{*/ +{ + return FileExists(File); +} + /*}}}*/ +std::string pkgDebianIndexRealFile::Describe(bool const /*Short*/) const/*{{{*/ +{ + return File; +} + /*}}}*/ +std::string pkgDebianIndexRealFile::ArchiveURI(std::string const &/*File*/) const/*{{{*/ +{ + return "file:" + File; +} + /*}}}*/ +std::string pkgDebianIndexRealFile::IndexFileName() const /*{{{*/ +{ + return File; +} + /*}}}*/ +std::string pkgDebianIndexRealFile::GetProgressDescription() const +{ + return File; +} +bool pkgDebianIndexRealFile::OpenListFile(FileFd &Pkg, std::string const &FileName)/*{{{*/ +{ + if (Pkg.Open(FileName, FileFd::ReadOnly, FileFd::None) == false) + return _error->Error("Problem opening %s",FileName.c_str()); + return true; +} + /*}}}*/ + +pkgDebianIndexFile::pkgDebianIndexFile(bool const Trusted) : pkgIndexFile(Trusted) +{ +} +pkgDebianIndexFile::~pkgDebianIndexFile() +{ +} +pkgCacheListParser * pkgDebianIndexFile::CreateListParser(FileFd &Pkg) +{ + if (Pkg.IsOpen() == false) + return NULL; + _error->PushToStack(); + pkgCacheListParser * const Parser = new debListParser(&Pkg); + bool const newError = _error->PendingError(); + _error->MergeWithStack(); + return newError ? NULL : Parser; +} +bool pkgDebianIndexFile::Merge(pkgCacheGenerator &Gen,OpProgress * const Prog) +{ + std::string const PackageFile = IndexFileName(); + FileFd Pkg; + if (OpenListFile(Pkg, PackageFile) == false) + return false; + _error->PushToStack(); + std::unique_ptr<pkgCacheListParser> Parser(CreateListParser(Pkg)); + bool const newError = _error->PendingError(); + if (newError == false && Parser == nullptr) + return true; + if (Parser == NULL) + return false; + + if (Prog != NULL) + Prog->SubProgress(0, GetProgressDescription()); + + if (Gen.SelectFile(PackageFile, *this, GetArchitecture(), GetComponent(), GetIndexFlags()) == false) + return _error->Error("Problem with SelectFile %s",PackageFile.c_str()); + + // Store the IMS information + pkgCache::PkgFileIterator File = Gen.GetCurFile(); + pkgCacheGenerator::Dynamic<pkgCache::PkgFileIterator> DynFile(File); + File->Size = Pkg.FileSize(); + File->mtime = Pkg.ModificationTime(); + + if (Gen.MergeList(*Parser) == false) + return _error->Error("Problem with MergeList %s",PackageFile.c_str()); + return true; +} +pkgCache::PkgFileIterator pkgDebianIndexFile::FindInCache(pkgCache &Cache) const +{ + std::string const FileName = IndexFileName(); + pkgCache::PkgFileIterator File = Cache.FileBegin(); + for (; File.end() == false; ++File) + { + if (File.FileName() == NULL || FileName != File.FileName()) + continue; + + struct stat St; + if (stat(File.FileName(),&St) != 0) + { + if (_config->FindB("Debug::pkgCacheGen", false)) + std::clog << "DebianIndexFile::FindInCache - stat failed on " << File.FileName() << std::endl; + return pkgCache::PkgFileIterator(Cache); + } + if ((map_filesize_t)St.st_size != File->Size || St.st_mtime != File->mtime) + { + if (_config->FindB("Debug::pkgCacheGen", false)) + std::clog << "DebianIndexFile::FindInCache - size (" << St.st_size << " <> " << File->Size + << ") or mtime (" << St.st_mtime << " <> " << File->mtime + << ") doesn't match for " << File.FileName() << std::endl; + return pkgCache::PkgFileIterator(Cache); + } + return File; + } + + return File; +} + +APT_CONST pkgIndexFile::~pkgIndexFile() {} +APT_CONST pkgDebianIndexTargetFile::~pkgDebianIndexTargetFile() {} +APT_CONST pkgDebianIndexRealFile::~pkgDebianIndexRealFile() {} diff --git a/apt-pkg/indexfile.h b/apt-pkg/indexfile.h index 817165f08..844f0cd3b 100644 --- a/apt-pkg/indexfile.h +++ b/apt-pkg/indexfile.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: indexfile.h,v 1.6.2.1 2003/12/24 23:09:17 mdz Exp $ /* ###################################################################### Index File - Abstraction for an index of archive/source file. @@ -28,6 +27,7 @@ #include <apt-pkg/cacheiterators.h> #include <apt-pkg/macros.h> +#include <map> #include <string> #ifndef APT_8_CLEANER_HEADERS @@ -38,28 +38,80 @@ class pkgAcquire; #endif class pkgCacheGenerator; +class pkgCacheListParser; class OpProgress; +class IndexTarget /*{{{*/ +/** \brief Information about an index file. */ +{ + public: + /** \brief A URI from which the index file can be downloaded. */ + std::string URI; + + /** \brief A description of the index file. */ + std::string Description; + + /** \brief A shorter description of the index file. */ + std::string ShortDesc; + + /** \brief The key by which this index file should be + looked up within the meta index file. */ + std::string MetaKey; + + /** \brief Is it okay if the file isn't found in the meta index */ + bool IsOptional; + + /** \brief If the file is downloaded compressed, do not unpack it */ + bool KeepCompressed; + + /** \brief options with which this target was created + Prefer the usage of #Option if at all possible. + Beware: Not all of these options are intended for public use */ + std::map<std::string, std::string> Options; + + IndexTarget(std::string const &MetaKey, std::string const &ShortDesc, + std::string const &LongDesc, std::string const &URI, bool const IsOptional, + bool const KeepCompressed, std::map<std::string, std::string> const &Options); + + enum OptionKeys { + SITE, + RELEASE, + COMPONENT, + LANGUAGE, + ARCHITECTURE, + BASE_URI, + REPO_URI, + CREATED_BY, + TARGET_OF, + FILENAME, + EXISTING_FILENAME, + }; + std::string Option(OptionKeys const Key) const; + std::string Format(std::string format) const; +}; + /*}}}*/ + class pkgIndexFile { + void * const d; protected: bool Trusted; - + public: class Type { public: - + // Global list of Items supported static Type **GlobalList; static unsigned long GlobalListLen; - static Type *GetType(const char *Type) APT_PURE; + static Type *GetType(const char * const Type) APT_PURE; const char *Label; - virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator /*File*/) const {return 0;}; - virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string /*File*/) const {return 0;}; + virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator const &/*File*/) const {return 0;}; + virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string const &/*File*/) const {return 0;}; Type(); virtual ~Type() {}; }; @@ -67,13 +119,13 @@ class pkgIndexFile virtual const Type *GetType() const = 0; // Return descriptive strings of various sorts - virtual std::string ArchiveInfo(pkgCache::VerIterator Ver) const; + virtual std::string ArchiveInfo(pkgCache::VerIterator const &Ver) const; virtual std::string SourceInfo(pkgSrcRecords::Parser const &Record, pkgSrcRecords::File const &File) const; - virtual std::string Describe(bool Short = false) const = 0; + virtual std::string Describe(bool const Short = false) const = 0; // Interface for acquire - virtual std::string ArchiveURI(std::string /*File*/) const {return std::string();}; + virtual std::string ArchiveURI(std::string const &/*File*/) const {return std::string();}; // Interface for the record parsers virtual pkgSrcRecords::Parser *CreateSrcParser() const {return 0;}; @@ -82,22 +134,77 @@ class pkgIndexFile virtual bool Exists() const = 0; virtual bool HasPackages() const = 0; virtual unsigned long Size() const = 0; - virtual bool Merge(pkgCacheGenerator &/*Gen*/, OpProgress* /*Prog*/) const { return false; }; - APT_DEPRECATED virtual bool Merge(pkgCacheGenerator &Gen, OpProgress &Prog) const - { return Merge(Gen, &Prog); }; - virtual bool MergeFileProvides(pkgCacheGenerator &/*Gen*/,OpProgress* /*Prog*/) const {return true;}; - APT_DEPRECATED virtual bool MergeFileProvides(pkgCacheGenerator &Gen, OpProgress &Prog) const - {return MergeFileProvides(Gen, &Prog);}; + virtual bool Merge(pkgCacheGenerator &/*Gen*/, OpProgress* const /*Prog*/) { return true; }; virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const; static bool TranslationsAvailable(); - static bool CheckLanguageCode(const char *Lang); + static bool CheckLanguageCode(const char * const Lang); static std::string LanguageCode(); bool IsTrusted() const { return Trusted; }; - - pkgIndexFile(bool Trusted): Trusted(Trusted) {}; - virtual ~pkgIndexFile() {}; + + explicit pkgIndexFile(bool const Trusted); + virtual ~pkgIndexFile(); +}; + +class pkgDebianIndexFile : public pkgIndexFile +{ +protected: + virtual std::string IndexFileName() const = 0; + virtual std::string GetComponent() const = 0; + virtual std::string GetArchitecture() const = 0; + virtual std::string GetProgressDescription() const = 0; + virtual uint8_t GetIndexFlags() const = 0; + virtual bool OpenListFile(FileFd &Pkg, std::string const &FileName) = 0; + APT_HIDDEN virtual pkgCacheListParser * CreateListParser(FileFd &Pkg); + +public: + virtual bool Merge(pkgCacheGenerator &Gen, OpProgress* const Prog) APT_OVERRIDE; + virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const APT_OVERRIDE; + + pkgDebianIndexFile(bool const Trusted); + virtual ~pkgDebianIndexFile(); +}; + +class pkgDebianIndexTargetFile : public pkgDebianIndexFile +{ + void * const d; +protected: + IndexTarget const Target; + + virtual std::string IndexFileName() const APT_OVERRIDE; + virtual std::string GetComponent() const APT_OVERRIDE; + virtual std::string GetArchitecture() const APT_OVERRIDE; + virtual std::string GetProgressDescription() const APT_OVERRIDE; + virtual bool OpenListFile(FileFd &Pkg, std::string const &FileName) APT_OVERRIDE; + +public: + virtual std::string ArchiveURI(std::string const &File) const APT_OVERRIDE; + virtual std::string Describe(bool const Short = false) const APT_OVERRIDE; + virtual bool Exists() const APT_OVERRIDE; + virtual unsigned long Size() const APT_OVERRIDE; + + pkgDebianIndexTargetFile(IndexTarget const &Target, bool const Trusted); + virtual ~pkgDebianIndexTargetFile(); +}; + +class pkgDebianIndexRealFile : public pkgDebianIndexFile +{ + void * const d; +protected: + std::string File; + + virtual std::string IndexFileName() const APT_OVERRIDE; + virtual std::string GetProgressDescription() const APT_OVERRIDE; + virtual bool OpenListFile(FileFd &Pkg, std::string const &FileName) APT_OVERRIDE; +public: + virtual std::string Describe(bool const /*Short*/ = false) const APT_OVERRIDE; + virtual bool Exists() const APT_OVERRIDE; + virtual unsigned long Size() const APT_OVERRIDE; + virtual std::string ArchiveURI(std::string const &/*File*/) const APT_OVERRIDE; + + pkgDebianIndexRealFile(std::string const &File, bool const Trusted); + virtual ~pkgDebianIndexRealFile(); }; #endif diff --git a/apt-pkg/indexrecords.cc b/apt-pkg/indexrecords.cc deleted file mode 100644 index de2617833..000000000 --- a/apt-pkg/indexrecords.cc +++ /dev/null @@ -1,296 +0,0 @@ -// -*- mode: cpp; mode: fold -*- -// Description /*{{{*/ -// $Id: indexrecords.cc,v 1.1.2.4 2003/12/30 02:11:43 mdz Exp $ - /*}}}*/ -// Include Files /*{{{*/ -#include<config.h> - -#include <apt-pkg/indexrecords.h> -#include <apt-pkg/tagfile.h> -#include <apt-pkg/error.h> -#include <apt-pkg/strutl.h> -#include <apt-pkg/configuration.h> -#include <apt-pkg/fileutl.h> -#include <apt-pkg/hashes.h> -#include <apt-pkg/gpgv.h> - -#include <stdlib.h> -#include <time.h> -#include <clocale> -#include <map> -#include <string> -#include <utility> -#include <vector> - -#include <apti18n.h> - /*}}}*/ - -using std::string; - -APT_PURE string indexRecords::GetDist() const -{ - return this->Dist; -} - -APT_PURE string indexRecords::GetSuite() const -{ - return this->Suite; -} - -APT_PURE bool indexRecords::GetSupportsAcquireByHash() const -{ - return this->SupportsAcquireByHash; -} - -APT_PURE bool indexRecords::CheckDist(const string MaybeDist) const -{ - return (this->Dist == MaybeDist - || this->Suite == MaybeDist); -} - -APT_PURE string indexRecords::GetExpectedDist() const -{ - return this->ExpectedDist; -} - -APT_PURE time_t indexRecords::GetValidUntil() const -{ - return this->ValidUntil; -} - -APT_PURE time_t indexRecords::GetDate() const -{ - return this->Date; -} - -APT_PURE indexRecords::checkSum *indexRecords::Lookup(const string MetaKey) -{ - std::map<std::string, indexRecords::checkSum* >::const_iterator sum = Entries.find(MetaKey); - if (sum == Entries.end()) - return NULL; - return sum->second; -} - -APT_PURE bool indexRecords::Exists(string const &MetaKey) const -{ - return Entries.count(MetaKey) == 1; -} - -bool indexRecords::Load(const string Filename) /*{{{*/ -{ - FileFd Fd; - if (OpenMaybeClearSignedFile(Filename, Fd) == false) - return false; - - pkgTagFile TagFile(&Fd, Fd.Size()); - if (_error->PendingError() == true) - { - strprintf(ErrorText, _("Unable to parse Release file %s"),Filename.c_str()); - return false; - } - - pkgTagSection Section; - const char *Start, *End; - if (TagFile.Step(Section) == false) - { - strprintf(ErrorText, _("No sections in Release file %s"), Filename.c_str()); - return false; - } - // FIXME: find better tag name - SupportsAcquireByHash = Section.FindB("Acquire-By-Hash", false); - - Suite = Section.FindS("Suite"); - Dist = Section.FindS("Codename"); - - bool FoundHashSum = false; - for (int i=0;HashString::SupportedHashes()[i] != NULL; i++) - { - if (!Section.Find(HashString::SupportedHashes()[i], Start, End)) - continue; - - string Name; - string Hash; - unsigned long long Size; - while (Start < End) - { - if (!parseSumData(Start, End, Name, Hash, Size)) - return false; - - if (Entries.find(Name) == Entries.end()) - { - indexRecords::checkSum *Sum = new indexRecords::checkSum; - Sum->MetaKeyFilename = Name; - Sum->Size = Size; - std::string SizeStr; - strprintf(SizeStr, "%llu", Size); - Sum->Hashes.push_back(HashString("Checksum-FileSize", SizeStr)); - APT_IGNORE_DEPRECATED(Sum->Hash = HashString(HashString::SupportedHashes()[i],Hash);) - Entries[Name] = Sum; - } - Entries[Name]->Hashes.push_back(HashString(HashString::SupportedHashes()[i],Hash)); - FoundHashSum = true; - } - } - - if(FoundHashSum == false) - { - strprintf(ErrorText, _("No Hash entry in Release file %s"), Filename.c_str()); - return false; - } - - string const StrDate = Section.FindS("Date"); - if (RFC1123StrToTime(StrDate.c_str(), Date) == false) - { - strprintf(ErrorText, _("Invalid 'Date' entry in Release file %s"), Filename.c_str()); - return false; - } - - string const Label = Section.FindS("Label"); - string const StrValidUntil = Section.FindS("Valid-Until"); - - // if we have a Valid-Until header in the Release file, use it as default - if (StrValidUntil.empty() == false) - { - if(RFC1123StrToTime(StrValidUntil.c_str(), ValidUntil) == false) - { - strprintf(ErrorText, _("Invalid 'Valid-Until' entry in Release file %s"), Filename.c_str()); - return false; - } - } - // get the user settings for this archive and use what expires earlier - int MaxAge = _config->FindI("Acquire::Max-ValidTime", 0); - if (Label.empty() == false) - MaxAge = _config->FindI(("Acquire::Max-ValidTime::" + Label).c_str(), MaxAge); - int MinAge = _config->FindI("Acquire::Min-ValidTime", 0); - if (Label.empty() == false) - MinAge = _config->FindI(("Acquire::Min-ValidTime::" + Label).c_str(), MinAge); - - if(MaxAge == 0 && - (MinAge == 0 || ValidUntil == 0)) // No user settings, use the one from the Release file - return true; - - if (MinAge != 0 && ValidUntil != 0) { - time_t const min_date = Date + MinAge; - if (ValidUntil < min_date) - ValidUntil = min_date; - } - if (MaxAge != 0) { - time_t const max_date = Date + MaxAge; - if (ValidUntil == 0 || ValidUntil > max_date) - ValidUntil = max_date; - } - - return true; -} - /*}}}*/ -std::vector<string> indexRecords::MetaKeys() /*{{{*/ -{ - std::vector<std::string> keys; - std::map<string,checkSum *>::iterator I = Entries.begin(); - while(I != Entries.end()) { - keys.push_back((*I).first); - ++I; - } - return keys; -} - /*}}}*/ -bool indexRecords::parseSumData(const char *&Start, const char *End, /*{{{*/ - string &Name, string &Hash, unsigned long long &Size) -{ - Name = ""; - Hash = ""; - Size = 0; - /* Skip over the first blank */ - while ((*Start == '\t' || *Start == ' ' || *Start == '\n' || *Start == '\r') - && Start < End) - Start++; - if (Start >= End) - return false; - - /* Move EntryEnd to the end of the first entry (the hash) */ - const char *EntryEnd = Start; - while ((*EntryEnd != '\t' && *EntryEnd != ' ') - && EntryEnd < End) - EntryEnd++; - if (EntryEnd == End) - return false; - - Hash.append(Start, EntryEnd-Start); - - /* Skip over intermediate blanks */ - Start = EntryEnd; - while (*Start == '\t' || *Start == ' ') - Start++; - if (Start >= End) - return false; - - EntryEnd = Start; - /* Find the end of the second entry (the size) */ - while ((*EntryEnd != '\t' && *EntryEnd != ' ' ) - && EntryEnd < End) - EntryEnd++; - if (EntryEnd == End) - return false; - - Size = strtoull (Start, NULL, 10); - - /* Skip over intermediate blanks */ - Start = EntryEnd; - while (*Start == '\t' || *Start == ' ') - Start++; - if (Start >= End) - return false; - - EntryEnd = Start; - /* Find the end of the third entry (the filename) */ - while ((*EntryEnd != '\t' && *EntryEnd != ' ' && - *EntryEnd != '\n' && *EntryEnd != '\r') - && EntryEnd < End) - EntryEnd++; - - Name.append(Start, EntryEnd-Start); - Start = EntryEnd; //prepare for the next round - return true; -} - /*}}}*/ - -APT_PURE bool indexRecords::IsAlwaysTrusted() const -{ - if (Trusted == ALWAYS_TRUSTED) - return true; - return false; -} -APT_PURE bool indexRecords::IsNeverTrusted() const -{ - if (Trusted == NEVER_TRUSTED) - return true; - return false; -} -void indexRecords::SetTrusted(bool const Trusted) -{ - if (Trusted == true) - this->Trusted = ALWAYS_TRUSTED; - else - this->Trusted = NEVER_TRUSTED; -} - -#if APT_PKG_ABI >= 413 -indexRecords::indexRecords(const string &ExpectedDist) : - Trusted(CHECK_TRUST), d(NULL), ExpectedDist(ExpectedDist), ValidUntil(0), - SupportsAcquireByHash(false) -{ -} -#else -indexRecords::indexRecords() : - Trusted(CHECK_TRUST), d(NULL), ExpectedDist(""), ValidUntil(0), - SupportsAcquireByHash(false) -{ -} -indexRecords::indexRecords(const string ExpectedDist) : - Trusted(CHECK_TRUST), d(NULL), ExpectedDist(ExpectedDist), ValidUntil(0), - SupportsAcquireByHash(false) -{ -} -#endif - -indexRecords::~indexRecords() {} diff --git a/apt-pkg/indexrecords.h b/apt-pkg/indexrecords.h deleted file mode 100644 index 6ed5f0c2b..000000000 --- a/apt-pkg/indexrecords.h +++ /dev/null @@ -1,96 +0,0 @@ -// -*- mode: cpp; mode: fold -*- -// Description /*{{{*/ -// $Id: indexrecords.h,v 1.1.2.1 2003/12/24 23:09:17 mdz Exp $ - /*}}}*/ -#ifndef PKGLIB_INDEXRECORDS_H -#define PKGLIB_INDEXRECORDS_H - -#include <apt-pkg/hashes.h> - -#include <map> -#include <vector> -#include <ctime> -#include <string> - -#ifndef APT_8_CLEANER_HEADERS -#include <apt-pkg/fileutl.h> -#endif -#ifndef APT_10_CLEANER_HEADERS -#include <apt-pkg/pkgcache.h> -#endif - -class indexRecords -{ - APT_HIDDEN bool parseSumData(const char *&Start, const char *End, std::string &Name, - std::string &Hash, unsigned long long &Size); - public: - struct checkSum; - std::string ErrorText; - - private: - enum APT_HIDDEN { ALWAYS_TRUSTED, NEVER_TRUSTED, CHECK_TRUST } Trusted; - // dpointer (for later) - void * d; - - protected: - std::string Dist; - std::string Suite; - std::string ExpectedDist; - time_t Date; - time_t ValidUntil; - bool SupportsAcquireByHash; - - std::map<std::string,checkSum *> Entries; - - public: -#if APT_PKG_ABI >= 413 - indexRecords(const std::string &ExpectedDist = ""); -#else - indexRecords(); - indexRecords(const std::string ExpectedDist); -#endif - - // Lookup function - virtual checkSum *Lookup(const std::string MetaKey); - /** \brief tests if a checksum for this file is available */ - bool Exists(std::string const &MetaKey) const; - std::vector<std::string> MetaKeys(); - - virtual bool Load(std::string Filename); - virtual bool CheckDist(const std::string MaybeDist) const; - - std::string GetDist() const; - std::string GetSuite() const; - bool GetSupportsAcquireByHash() const; - time_t GetValidUntil() const; - time_t GetDate() const; - std::string GetExpectedDist() const; - - /** \brief check if source is marked as always trusted */ - bool IsAlwaysTrusted() const; - /** \brief check if source is marked as never trusted */ - bool IsNeverTrusted() const; - - /** \brief sets an explicit trust value - * - * \b true means that the source should always be considered trusted, - * while \b false marks a source as always untrusted, even if we have - * a valid signature and everything. - */ - void SetTrusted(bool const Trusted); - - virtual ~indexRecords(); -}; - -APT_IGNORE_DEPRECATED_PUSH -struct indexRecords::checkSum -{ - std::string MetaKeyFilename; - HashStringList Hashes; - unsigned long long Size; - - APT_DEPRECATED HashString Hash; -}; -APT_IGNORE_DEPRECATED_POP - -#endif diff --git a/apt-pkg/init.cc b/apt-pkg/init.cc index f756eab26..eab198fac 100644 --- a/apt-pkg/init.cc +++ b/apt-pkg/init.cc @@ -18,7 +18,6 @@ #include <apt-pkg/macros.h> #include <string.h> -#include <string> #include <cstdlib> #include <apti18n.h> @@ -62,8 +61,6 @@ bool pkgInitConfig(Configuration &Cnf) Cnf.CndSet("Dir::Etc","etc/apt/"); Cnf.CndSet("Dir::Etc::sourcelist","sources.list"); Cnf.CndSet("Dir::Etc::sourceparts","sources.list.d"); - Cnf.CndSet("Dir::Etc::vendorlist","vendors.list"); - Cnf.CndSet("Dir::Etc::vendorparts","vendors.list.d"); Cnf.CndSet("Dir::Etc::main","apt.conf"); Cnf.CndSet("Dir::Etc::netrc", "auth.conf"); Cnf.CndSet("Dir::Etc::parts","apt.conf.d"); @@ -101,8 +98,31 @@ bool pkgInitConfig(Configuration &Cnf) // The default user we drop to in the methods Cnf.CndSet("APT::Sandbox::User", "_apt"); + Cnf.CndSet("Acquire::IndexTargets::deb::Packages::MetaKey", "$(COMPONENT)/binary-$(ARCHITECTURE)/Packages"); + Cnf.CndSet("Acquire::IndexTargets::deb::Packages::flatMetaKey", "Packages"); + Cnf.CndSet("Acquire::IndexTargets::deb::Packages::ShortDescription", "Packages"); + Cnf.CndSet("Acquire::IndexTargets::deb::Packages::Description", "$(RELEASE)/$(COMPONENT) $(ARCHITECTURE) Packages"); + Cnf.CndSet("Acquire::IndexTargets::deb::Packages::flatDescription", "$(RELEASE) Packages"); + Cnf.CndSet("Acquire::IndexTargets::deb::Packages::Optional", false); + Cnf.CndSet("Acquire::IndexTargets::deb::Translations::MetaKey", "$(COMPONENT)/i18n/Translation-$(LANGUAGE)"); + Cnf.CndSet("Acquire::IndexTargets::deb::Translations::flatMetaKey", "$(LANGUAGE)"); + Cnf.CndSet("Acquire::IndexTargets::deb::Translations::ShortDescription", "Translation-$(LANGUAGE)"); + Cnf.CndSet("Acquire::IndexTargets::deb::Translations::Description", "$(RELEASE)/$(COMPONENT) Translation-$(LANGUAGE)"); + Cnf.CndSet("Acquire::IndexTargets::deb::Translations::flatDescription", "$(RELEASE) Translation-$(LANGUAGE)"); + Cnf.CndSet("Acquire::IndexTargets::deb-src::Sources::MetaKey", "$(COMPONENT)/source/Sources"); + Cnf.CndSet("Acquire::IndexTargets::deb-src::Sources::flatMetaKey", "Sources"); + Cnf.CndSet("Acquire::IndexTargets::deb-src::Sources::ShortDescription", "Sources"); + Cnf.CndSet("Acquire::IndexTargets::deb-src::Sources::Description", "$(RELEASE)/$(COMPONENT) Sources"); + Cnf.CndSet("Acquire::IndexTargets::deb-src::Sources::flatDescription", "$(RELEASE) Sources"); + Cnf.CndSet("Acquire::IndexTargets::deb-src::Sources::Optional", false); + + Cnf.CndSet("Acquire::Changelogs::URI::Origin::Debian", "http://metadata.ftp-master.debian.org/changelogs/CHANGEPATH_changelog"); + Cnf.CndSet("Acquire::Changelogs::URI::Origin::Tanglu", "http://metadata.tanglu.org/changelogs/CHANGEPATH_changelog"); + Cnf.CndSet("Acquire::Changelogs::URI::Origin::Ubuntu", "http://changelogs.ubuntu.com/changelogs/pool/CHANGEPATH/changelog"); + Cnf.CndSet("Acquire::Changelogs::URI::Origin::Ultimedia", "http://packages.ultimediaos.com/changelogs/pool/CHANGEPATH/changelog.txt"); + bool Res = true; - + // Read an alternate config file const char *Cfg = getenv("APT_CONFIG"); if (Cfg != 0 && strlen(Cfg) != 0) diff --git a/apt-pkg/install-progress.cc b/apt-pkg/install-progress.cc index 5ea8bf4d0..14409e301 100644 --- a/apt-pkg/install-progress.cc +++ b/apt-pkg/install-progress.cc @@ -8,13 +8,12 @@ #include <signal.h> #include <unistd.h> #include <iostream> -#include <string> #include <vector> #include <sys/ioctl.h> -#include <sstream> #include <fcntl.h> #include <algorithm> #include <stdio.h> +#include <sstream> #include <apti18n.h> @@ -65,10 +64,11 @@ bool PackageManager::StatusChanged(std::string /*PackageName*/, } PackageManagerProgressFd::PackageManagerProgressFd(int progress_fd) - : StepsDone(0), StepsTotal(1) + : d(NULL), StepsDone(0), StepsTotal(1) { OutStatusFd = progress_fd; } +PackageManagerProgressFd::~PackageManagerProgressFd() {} void PackageManagerProgressFd::WriteToStatusFd(std::string s) { @@ -153,10 +153,11 @@ bool PackageManagerProgressFd::StatusChanged(std::string PackageName, PackageManagerProgressDeb822Fd::PackageManagerProgressDeb822Fd(int progress_fd) - : StepsDone(0), StepsTotal(1) + : d(NULL), StepsDone(0), StepsTotal(1) { OutStatusFd = progress_fd; } +PackageManagerProgressDeb822Fd::~PackageManagerProgressDeb822Fd() {} void PackageManagerProgressDeb822Fd::WriteToStatusFd(std::string s) { @@ -233,7 +234,7 @@ bool PackageManagerProgressDeb822Fd::StatusChanged(std::string PackageName, PackageManagerFancy::PackageManagerFancy() - : child_pty(-1) + : d(NULL), child_pty(-1) { // setup terminal size old_SIGWINCH = signal(SIGWINCH, PackageManagerFancy::staticSIGWINCH); @@ -285,13 +286,13 @@ void PackageManagerFancy::SetupTerminalScrollArea(int nr_rows) std::cout << "\n"; // save cursor - std::cout << "\033[s"; + std::cout << "\0337"; // set scroll region (this will place the cursor in the top left) std::cout << "\033[0;" << nr_rows - 1 << "r"; // restore cursor but ensure its inside the scrolling area - std::cout << "\033[u"; + std::cout << "\0338"; static const char *move_cursor_up = "\033[1A"; std::cout << move_cursor_up; @@ -373,8 +374,8 @@ bool PackageManagerFancy::DrawStatusLine() if (unlikely(size.rows < 1 || size.columns < 1)) return false; - static std::string save_cursor = "\033[s"; - static std::string restore_cursor = "\033[u"; + static std::string save_cursor = "\0337"; + static std::string restore_cursor = "\0338"; // green static std::string set_bg_color = DeQuoteString( @@ -433,6 +434,10 @@ bool PackageManagerText::StatusChanged(std::string PackageName, return true; } +PackageManagerText::PackageManagerText() : PackageManager(), d(NULL) {} +PackageManagerText::~PackageManagerText() {} + + } // namespace progress diff --git a/apt-pkg/install-progress.h b/apt-pkg/install-progress.h index d8b4a5c82..ee03ac217 100644 --- a/apt-pkg/install-progress.h +++ b/apt-pkg/install-progress.h @@ -18,7 +18,7 @@ namespace Progress { { private: /** \brief dpointer placeholder */ - void *d; + void * const d; protected: std::string progress_str; @@ -61,6 +61,7 @@ namespace Progress { class PackageManagerProgressFd : public PackageManager { + void * const d; protected: int OutStatusFd; int StepsDone; @@ -68,28 +69,30 @@ namespace Progress { void WriteToStatusFd(std::string msg); public: - PackageManagerProgressFd(int progress_fd); + explicit PackageManagerProgressFd(int progress_fd); + virtual ~PackageManagerProgressFd(); - virtual void StartDpkg(); - virtual void Stop(); + virtual void StartDpkg() APT_OVERRIDE; + virtual void Stop() APT_OVERRIDE; virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps, - std::string HumanReadableAction); + std::string HumanReadableAction) APT_OVERRIDE; virtual void Error(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps, - std::string ErrorMessage); + std::string ErrorMessage) APT_OVERRIDE; virtual void ConffilePrompt(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps, - std::string ConfMessage); + std::string ConfMessage) APT_OVERRIDE; }; class PackageManagerProgressDeb822Fd : public PackageManager { + void * const d; protected: int OutStatusFd; int StepsDone; @@ -97,27 +100,29 @@ namespace Progress { void WriteToStatusFd(std::string msg); public: - PackageManagerProgressDeb822Fd(int progress_fd); + explicit PackageManagerProgressDeb822Fd(int progress_fd); + virtual ~PackageManagerProgressDeb822Fd(); - virtual void StartDpkg(); - virtual void Stop(); + virtual void StartDpkg() APT_OVERRIDE; + virtual void Stop() APT_OVERRIDE; virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps, - std::string HumanReadableAction); + std::string HumanReadableAction) APT_OVERRIDE; virtual void Error(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps, - std::string ErrorMessage); + std::string ErrorMessage) APT_OVERRIDE; virtual void ConffilePrompt(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps, - std::string ConfMessage); + std::string ConfMessage) APT_OVERRIDE; }; class PackageManagerFancy : public PackageManager { + void * const d; private: APT_HIDDEN static void staticSIGWINCH(int); static std::vector<PackageManagerFancy*> instances; @@ -138,13 +143,13 @@ namespace Progress { public: PackageManagerFancy(); - ~PackageManagerFancy(); - virtual void Start(int child_pty=-1); - virtual void Stop(); + virtual ~PackageManagerFancy(); + virtual void Start(int child_pty=-1) APT_OVERRIDE; + virtual void Stop() APT_OVERRIDE; virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps, - std::string HumanReadableAction); + std::string HumanReadableAction) APT_OVERRIDE; // return a progress bar of the given size for the given progress // percent between 0.0 and 1.0 in the form "[####...]" @@ -153,11 +158,15 @@ namespace Progress { class PackageManagerText : public PackageManager { + void * const d; public: virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps, - std::string HumanReadableAction); + std::string HumanReadableAction) APT_OVERRIDE; + + PackageManagerText(); + virtual ~PackageManagerText(); }; diff --git a/apt-pkg/metaindex.cc b/apt-pkg/metaindex.cc index 31a8ec009..1632b928c 100644 --- a/apt-pkg/metaindex.cc +++ b/apt-pkg/metaindex.cc @@ -1,30 +1,31 @@ // Include Files /*{{{*/ +#include <apt-pkg/pkgcachegen.h> #include <apt-pkg/indexfile.h> #include <apt-pkg/metaindex.h> -#include <stddef.h> - #include <string> #include <vector> /*}}}*/ -#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) -std::string metaIndex::LocalFileName() const { return ""; } -#else -#include <apt-pkg/debmetaindex.h> -std::string metaIndex::LocalFileName() const +std::string metaIndex::Describe() const { - debReleaseIndex const * deb = dynamic_cast<debReleaseIndex const*>(this); - if (deb != NULL) - return deb->LocalFileName(); + return "Release"; +} - return ""; +pkgCache::RlsFileIterator metaIndex::FindInCache(pkgCache &Cache, bool const) const +{ + return pkgCache::RlsFileIterator(Cache); +} + +bool metaIndex::Merge(pkgCacheGenerator &Gen,OpProgress *) const +{ + return Gen.SelectReleaseFile("", ""); } -#endif metaIndex::metaIndex(std::string const &URI, std::string const &Dist, char const * const Type) -: Indexes(NULL), Type(Type), URI(URI), Dist(Dist), Trusted(false) +: d(NULL), Indexes(NULL), Type(Type), URI(URI), Dist(Dist), Trusted(TRI_UNSET), + Date(0), ValidUntil(0), SupportsAcquireByHash(false), LoadedSuccessfully(TRI_UNSET) { /* nothing */ } @@ -38,3 +39,61 @@ metaIndex::~metaIndex() delete *I; delete Indexes; } + +// one line Getters for public fields /*{{{*/ +APT_PURE std::string metaIndex::GetURI() const { return URI; } +APT_PURE std::string metaIndex::GetDist() const { return Dist; } +APT_PURE const char* metaIndex::GetType() const { return Type; } +APT_PURE metaIndex::TriState metaIndex::GetTrusted() const { return Trusted; } +APT_PURE std::string metaIndex::GetSignedBy() const { return SignedBy; } +APT_PURE std::string metaIndex::GetCodename() const { return Codename; } +APT_PURE std::string metaIndex::GetSuite() const { return Suite; } +APT_PURE bool metaIndex::GetSupportsAcquireByHash() const { return SupportsAcquireByHash; } +APT_PURE time_t metaIndex::GetValidUntil() const { return ValidUntil; } +APT_PURE time_t metaIndex::GetDate() const { return this->Date; } +APT_PURE metaIndex::TriState metaIndex::GetLoadedSuccessfully() const { return LoadedSuccessfully; } + +APT_PURE bool metaIndex::CheckDist(string const &MaybeDist) const +{ + return (this->Codename == MaybeDist + || this->Suite == MaybeDist); +} +APT_PURE std::string metaIndex::GetExpectedDist() const +{ + // TODO: Used to be an explicit value set in the constructor + return ""; +} + /*}}}*/ +APT_PURE metaIndex::checkSum *metaIndex::Lookup(string const &MetaKey) const /*{{{*/ +{ + std::map<std::string, metaIndex::checkSum* >::const_iterator sum = Entries.find(MetaKey); + if (sum == Entries.end()) + return NULL; + return sum->second; +} + /*}}}*/ +APT_PURE bool metaIndex::Exists(string const &MetaKey) const /*{{{*/ +{ + return Entries.find(MetaKey) != Entries.end(); +} + /*}}}*/ +std::vector<std::string> metaIndex::MetaKeys() const /*{{{*/ +{ + std::vector<std::string> keys; + std::map<string,checkSum *>::const_iterator I = Entries.begin(); + while(I != Entries.end()) { + keys.push_back((*I).first); + ++I; + } + return keys; +} + /*}}}*/ +void metaIndex::swapLoad(metaIndex * const OldMetaIndex) /*{{{*/ +{ + std::swap(Entries, OldMetaIndex->Entries); + std::swap(Date, OldMetaIndex->Date); + std::swap(ValidUntil, OldMetaIndex->ValidUntil); + std::swap(SupportsAcquireByHash, OldMetaIndex->SupportsAcquireByHash); + std::swap(LoadedSuccessfully, OldMetaIndex->LoadedSuccessfully); +} + /*}}}*/ diff --git a/apt-pkg/metaindex.h b/apt-pkg/metaindex.h index 6c3d2880b..94aec2d1f 100644 --- a/apt-pkg/metaindex.h +++ b/apt-pkg/metaindex.h @@ -17,41 +17,92 @@ class OpProgress; #ifndef APT_8_CLEANER_HEADERS #include <apt-pkg/srcrecords.h> #include <apt-pkg/pkgrecords.h> -#include <apt-pkg/vendor.h> using std::string; #endif class pkgAcquire; +class IndexTarget; +class pkgCacheGenerator; +class OpProgress; class metaIndex { - protected: +public: + APT_IGNORE_DEPRECATED_PUSH + struct checkSum + { + std::string MetaKeyFilename; + HashStringList Hashes; + unsigned long long Size; + + APT_DEPRECATED HashString Hash; + }; + APT_IGNORE_DEPRECATED_POP + + enum APT_HIDDEN TriState { + TRI_YES, TRI_DONTCARE, TRI_NO, TRI_UNSET + }; +private: + void * const d; +protected: std::vector <pkgIndexFile *> *Indexes; + // parsed from the sources.list const char *Type; std::string URI; std::string Dist; - bool Trusted; + TriState Trusted; + std::string SignedBy; - public: + // parsed from a file + std::string Suite; + std::string Codename; + time_t Date; + time_t ValidUntil; + bool SupportsAcquireByHash; + std::map<std::string, checkSum *> Entries; + TriState LoadedSuccessfully; +public: // Various accessors - virtual std::string GetURI() const {return URI;} - virtual std::string GetDist() const {return Dist;} - virtual const char* GetType() const {return Type;} - - // interface to to query it -#if APT_PKG_ABI >= 413 - /** \return the path of the local file (or "" if its not available) */ - virtual std::string LocalFileName() const; -#else - std::string LocalFileName() const; -#endif + std::string GetURI() const; + std::string GetDist() const; + const char* GetType() const; + TriState GetTrusted() const; + std::string GetSignedBy() const; + + std::string GetCodename() const; + std::string GetSuite() const; + bool GetSupportsAcquireByHash() const; + time_t GetValidUntil() const; + time_t GetDate() const; + + std::string GetExpectedDist() const; + bool CheckDist(std::string const &MaybeDist) const; // Interface for acquire + virtual std::string Describe() const; virtual std::string ArchiveURI(std::string const& File) const = 0; - virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false) const = 0; + virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false) = 0; + virtual std::vector<IndexTarget> GetIndexTargets() const = 0; virtual std::vector<pkgIndexFile *> *GetIndexFiles() = 0; virtual bool IsTrusted() const = 0; + virtual bool Load(std::string const &Filename, std::string * const ErrorText) = 0; + /** @return a new metaIndex object based on this one, but without information from #Load */ + virtual metaIndex * UnloadedClone() const = 0; + // the given metaIndex is potentially invalid after this call and should be deleted + void swapLoad(metaIndex * const OldMetaIndex); + + // Lookup functions for parsed Hashes + checkSum *Lookup(std::string const &MetaKey) const; + /** \brief tests if a checksum for this file is available */ + bool Exists(std::string const &MetaKey) const; + std::vector<std::string> MetaKeys() const; + TriState GetLoadedSuccessfully() const; + + // Interfaces for pkgCacheGen + virtual pkgCache::RlsFileIterator FindInCache(pkgCache &Cache, bool const ModifyCheck) const; + virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const; + metaIndex(std::string const &URI, std::string const &Dist, char const * const Type); diff --git a/apt-pkg/orderlist.cc b/apt-pkg/orderlist.cc index a1fcbcc98..1e0640422 100644 --- a/apt-pkg/orderlist.cc +++ b/apt-pkg/orderlist.cc @@ -68,14 +68,12 @@ #include <apt-pkg/orderlist.h> #include <apt-pkg/depcache.h> #include <apt-pkg/error.h> -#include <apt-pkg/sptr.h> #include <apt-pkg/configuration.h> #include <apt-pkg/cacheiterators.h> #include <apt-pkg/pkgcache.h> #include <stdlib.h> #include <string.h> -#include <string> #include <iostream> /*}}}*/ @@ -86,7 +84,7 @@ pkgOrderList *pkgOrderList::Me = 0; // OrderList::pkgOrderList - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ -pkgOrderList::pkgOrderList(pkgDepCache *pCache) : Cache(*pCache), +pkgOrderList::pkgOrderList(pkgDepCache *pCache) : d(NULL), Cache(*pCache), Primary(NULL), Secondary(NULL), RevDepends(NULL), Remove(NULL), AfterEnd(NULL), FileList(NULL), @@ -142,9 +140,9 @@ bool pkgOrderList::DoRun() { // Temp list unsigned long Size = Cache.Head().PackageCount; - SPtrArray<Package *> NList = new Package *[Size]; - SPtrArray<Package *> AfterList = new Package *[Size]; - AfterEnd = AfterList; + std::unique_ptr<Package *[]> NList(new Package *[Size]); + std::unique_ptr<Package *[]> AfterList(new Package *[Size]); + AfterEnd = AfterList.get(); Depth = 0; WipeFlags(Added | AddPending | Loop | InList); @@ -154,7 +152,7 @@ bool pkgOrderList::DoRun() // Rebuild the main list into the temp list. iterator OldEnd = End; - End = NList; + End = NList.get(); for (iterator I = List; I != OldEnd; ++I) if (VisitNode(PkgIterator(Cache,*I), "DoRun") == false) { @@ -163,12 +161,12 @@ bool pkgOrderList::DoRun() } // Copy the after list to the end of the main list - for (Package **I = AfterList; I != AfterEnd; I++) + for (Package **I = AfterList.get(); I != AfterEnd; I++) *End++ = *I; // Swap the main list to the new list delete [] List; - List = NList.UnGuard(); + List = NList.release(); return true; } /*}}}*/ @@ -512,8 +510,8 @@ bool pkgOrderList::VisitRProvides(DepFunc F,VerIterator Ver) against it! */ bool pkgOrderList::VisitProvides(DepIterator D,bool Critical) { - SPtrArray<Version *> List = D.AllTargets(); - for (Version **I = List; *I != 0; ++I) + std::unique_ptr<Version *[]> List(D.AllTargets()); + for (Version **I = List.get(); *I != 0; ++I) { VerIterator Ver(Cache,*I); PkgIterator Pkg = Ver.ParentPkg(); @@ -541,7 +539,7 @@ bool pkgOrderList::VisitProvides(DepIterator D,bool Critical) } if (D.IsNegative() == false) return true; - for (Version **I = List; *I != 0; ++I) + for (Version **I = List.get(); *I != 0; ++I) { VerIterator Ver(Cache,*I); PkgIterator Pkg = Ver.ParentPkg(); @@ -1075,9 +1073,9 @@ void pkgOrderList::WipeFlags(unsigned long F) this fails to produce a suitable result. */ bool pkgOrderList::CheckDep(DepIterator D) { - SPtrArray<Version *> List = D.AllTargets(); + std::unique_ptr<Version *[]> List(D.AllTargets()); bool Hit = false; - for (Version **I = List; *I != 0; I++) + for (Version **I = List.get(); *I != 0; I++) { VerIterator Ver(Cache,*I); PkgIterator Pkg = Ver.ParentPkg(); diff --git a/apt-pkg/orderlist.h b/apt-pkg/orderlist.h index b8bad81b3..7b35b2955 100644 --- a/apt-pkg/orderlist.h +++ b/apt-pkg/orderlist.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: orderlist.h,v 1.9 2001/02/20 07:03:17 jgg Exp $ /* ###################################################################### Order List - Represents and Manipulates an ordered list of packages. @@ -25,6 +24,7 @@ class pkgDepCache; class pkgOrderList : protected pkgCache::Namespace { + void * const d; protected: pkgDepCache &Cache; @@ -122,8 +122,8 @@ class pkgOrderList : protected pkgCache::Namespace int Score(PkgIterator Pkg); - pkgOrderList(pkgDepCache *Cache); - ~pkgOrderList(); + explicit pkgOrderList(pkgDepCache *Cache); + virtual ~pkgOrderList(); }; #endif diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc index d137dc75a..06ec986ed 100644 --- a/apt-pkg/packagemanager.cc +++ b/apt-pkg/packagemanager.cc @@ -23,7 +23,6 @@ #include <apt-pkg/acquire-item.h> #include <apt-pkg/algorithms.h> #include <apt-pkg/configuration.h> -#include <apt-pkg/sptr.h> #include <apt-pkg/macros.h> #include <apt-pkg/pkgcache.h> #include <apt-pkg/cacheiterators.h> @@ -45,7 +44,7 @@ bool pkgPackageManager::SigINTStop = false; // --------------------------------------------------------------------- /* */ pkgPackageManager::pkgPackageManager(pkgDepCache *pCache) : Cache(*pCache), - List(NULL), Res(Incomplete) + List(NULL), Res(Incomplete), d(NULL) { FileNames = new string[Cache.Head().PackageCount]; Debug = _config->FindB("Debug::pkgPackageManager",false); @@ -390,9 +389,9 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) // to do anything at all for (DepIterator Cur = Start; true; ++Cur) { - SPtrArray<Version *> VList = Cur.AllTargets(); + std::unique_ptr<Version *> VList(Cur.AllTargets()); - for (Version **I = VList; *I != 0; ++I) + for (Version **I = VList.get(); *I != 0; ++I) { VerIterator Ver(Cache,*I); PkgIterator DepPkg = Ver.ParentPkg(); @@ -440,9 +439,9 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) // probably due to loops. for (DepIterator Cur = Start; true; ++Cur) { - SPtrArray<Version *> VList = Cur.AllTargets(); + std::unique_ptr<Version *> VList(Cur.AllTargets()); - for (Version **I = VList; *I != 0; ++I) + for (Version **I = VList.get(); *I != 0; ++I) { VerIterator Ver(Cache,*I); PkgIterator DepPkg = Ver.ParentPkg(); @@ -515,9 +514,9 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) // Search for dependencies which are unpacked but aren't configured yet (maybe loops) for (DepIterator Cur = Start; true; ++Cur) { - SPtrArray<Version *> VList = Cur.AllTargets(); + std::unique_ptr<Version *> VList(Cur.AllTargets()); - for (Version **I = VList; *I != 0; ++I) + for (Version **I = VList.get(); *I != 0; ++I) { VerIterator Ver(Cache,*I); PkgIterator DepPkg = Ver.ParentPkg(); @@ -726,8 +725,8 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c // Look for easy targets: packages that are already okay for (DepIterator Cur = Start; Bad == true; ++Cur) { - SPtrArray<Version *> VList = Cur.AllTargets(); - for (Version **I = VList; *I != 0; ++I) + std::unique_ptr<Version *> VList(Cur.AllTargets()); + for (Version **I = VList.get(); *I != 0; ++I) { VerIterator Ver(Cache,*I); PkgIterator Pkg = Ver.ParentPkg(); @@ -750,8 +749,8 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c // Look for something that could be configured. for (DepIterator Cur = Start; Bad == true && Cur.end() == false; ++Cur) { - SPtrArray<Version *> VList = Cur.AllTargets(); - for (Version **I = VList; *I != 0; ++I) + std::unique_ptr<Version *[]> VList(Cur.AllTargets()); + for (Version **I = VList.get(); *I != 0; ++I) { VerIterator Ver(Cache,*I); PkgIterator DepPkg = Ver.ParentPkg(); @@ -806,8 +805,8 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c End->Type == pkgCache::Dep::Obsoletes || End->Type == pkgCache::Dep::DpkgBreaks) { - SPtrArray<Version *> VList = End.AllTargets(); - for (Version **I = VList; *I != 0; ++I) + std::unique_ptr<Version *[]> VList(End.AllTargets()); + for (Version **I = VList.get(); *I != 0; ++I) { VerIterator Ver(Cache,*I); PkgIterator ConflictPkg = Ver.ParentPkg(); @@ -1085,7 +1084,6 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall() // PM::DoInstallPostFork - compat /*{{{*/ // --------------------------------------------------------------------- /*}}}*/ -#if APT_PKG_ABI >= 413 pkgPackageManager::OrderResult pkgPackageManager::DoInstallPostFork(int statusFd) { @@ -1107,22 +1105,10 @@ pkgPackageManager::DoInstallPostFork(APT::Progress::PackageManager *progress) return Res; } -#else -pkgPackageManager::OrderResult -pkgPackageManager::DoInstallPostFork(int statusFd) -{ - bool goResult = Go(statusFd); - if(goResult == false) - return Failed; - - return Res; -} -#endif /*}}}*/ // PM::DoInstall - Does the installation /*{{{*/ // --------------------------------------------------------------------- /* compat */ -#if APT_PKG_ABI >= 413 pkgPackageManager::OrderResult pkgPackageManager::DoInstall(int statusFd) { @@ -1132,21 +1118,11 @@ pkgPackageManager::DoInstall(int statusFd) delete progress; return res; } -#else -pkgPackageManager::OrderResult pkgPackageManager::DoInstall(int statusFd) -{ - if(DoInstallPreFork() == Failed) - return Failed; - - return DoInstallPostFork(statusFd); -} -#endif /*}}}*/ // PM::DoInstall - Does the installation /*{{{*/ // --------------------------------------------------------------------- /* This uses the filenames in FileNames and the information in the DepCache to perform the installation of packages.*/ -#if APT_PKG_ABI >= 413 pkgPackageManager::OrderResult pkgPackageManager::DoInstall(APT::Progress::PackageManager *progress) { @@ -1155,5 +1131,4 @@ pkgPackageManager::DoInstall(APT::Progress::PackageManager *progress) return DoInstallPostFork(progress); } -#endif /*}}}*/ diff --git a/apt-pkg/packagemanager.h b/apt-pkg/packagemanager.h index fce0ad301..8de6ab3ad 100644 --- a/apt-pkg/packagemanager.h +++ b/apt-pkg/packagemanager.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: packagemanager.h,v 1.14 2001/05/07 04:24:08 jgg Exp $ /* ###################################################################### Package Manager - Abstacts the package manager @@ -96,9 +95,7 @@ class pkgPackageManager : protected pkgCache::Namespace virtual bool Install(PkgIterator /*Pkg*/,std::string /*File*/) {return false;}; virtual bool Configure(PkgIterator /*Pkg*/) {return false;}; virtual bool Remove(PkgIterator /*Pkg*/,bool /*Purge*/=false) {return false;}; -#if APT_PKG_ABI >= 413 virtual bool Go(APT::Progress::PackageManager * /*progress*/) {return true;}; -#endif virtual bool Go(int /*statusFd*/=-1) {return true;}; virtual void Reset() {}; @@ -113,13 +110,9 @@ class pkgPackageManager : protected pkgCache::Namespace pkgRecords *Recs); // Do the installation -#if APT_PKG_ABI >= 413 OrderResult DoInstall(APT::Progress::PackageManager *progress); // compat APT_DEPRECATED OrderResult DoInstall(int statusFd=-1); -#else - OrderResult DoInstall(int statusFd=-1); -#endif // stuff that needs to be done before the fork() of a library that // uses apt @@ -127,14 +120,10 @@ class pkgPackageManager : protected pkgCache::Namespace Res = OrderInstall(); return Res; }; -#if APT_PKG_ABI >= 413 // stuff that needs to be done after the fork OrderResult DoInstallPostFork(APT::Progress::PackageManager *progress); // compat APT_DEPRECATED OrderResult DoInstallPostFork(int statusFd=-1); -#else - OrderResult DoInstallPostFork(int statusFd=-1); -#endif // ? bool FixMissing(); @@ -142,10 +131,11 @@ class pkgPackageManager : protected pkgCache::Namespace /** \brief returns all packages dpkg let disappear */ inline std::set<std::string> GetDisappearedPackages() { return disappearedPkgs; }; - pkgPackageManager(pkgDepCache *Cache); + explicit pkgPackageManager(pkgDepCache *Cache); virtual ~pkgPackageManager(); private: + void * const d; enum APT_HIDDEN SmartAction { UNPACK_IMMEDIATE, UNPACK, CONFIGURE }; APT_HIDDEN bool NonLoopingSmart(SmartAction const action, pkgCache::PkgIterator &Pkg, pkgCache::PkgIterator DepPkg, int const Depth, bool const PkgLoop, diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index 864ae0f60..9d3929cd9 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -34,7 +34,8 @@ #include <stddef.h> #include <string.h> -#include <ostream> +#include <sstream> +#include <algorithm> #include <vector> #include <string> #include <sys/stat.h> @@ -50,41 +51,45 @@ using std::string; /* Simply initialize the header */ pkgCache::Header::Header() { - Signature = 0x98FE76DC; - +#define APT_HEADER_SET(X,Y) X = Y; static_assert(std::numeric_limits<decltype(X)>::max() > Y, "Size violation detected in pkgCache::Header") + APT_HEADER_SET(Signature, 0x98FE76DC); + /* Whenever the structures change the major version should be bumped, whenever the generator changes the minor version should be bumped. */ - MajorVersion = 10; - MinorVersion = 0; - Dirty = false; - - HeaderSz = sizeof(pkgCache::Header); - GroupSz = sizeof(pkgCache::Group); - PackageSz = sizeof(pkgCache::Package); - PackageFileSz = sizeof(pkgCache::PackageFile); - VersionSz = sizeof(pkgCache::Version); - DescriptionSz = sizeof(pkgCache::Description); - DependencySz = sizeof(pkgCache::Dependency); - ProvidesSz = sizeof(pkgCache::Provides); - VerFileSz = sizeof(pkgCache::VerFile); - DescFileSz = sizeof(pkgCache::DescFile); - + APT_HEADER_SET(MajorVersion, 10); + APT_HEADER_SET(MinorVersion, 0); + APT_HEADER_SET(Dirty, false); + + APT_HEADER_SET(HeaderSz, sizeof(pkgCache::Header)); + APT_HEADER_SET(GroupSz, sizeof(pkgCache::Group)); + APT_HEADER_SET(PackageSz, sizeof(pkgCache::Package)); + APT_HEADER_SET(ReleaseFileSz, sizeof(pkgCache::ReleaseFile)); + APT_HEADER_SET(PackageFileSz, sizeof(pkgCache::PackageFile)); + APT_HEADER_SET(VersionSz, sizeof(pkgCache::Version)); + APT_HEADER_SET(DescriptionSz, sizeof(pkgCache::Description)); + APT_HEADER_SET(DependencySz, sizeof(pkgCache::Dependency)); + APT_HEADER_SET(DependencyDataSz, sizeof(pkgCache::DependencyData)); + APT_HEADER_SET(ProvidesSz, sizeof(pkgCache::Provides)); + APT_HEADER_SET(VerFileSz, sizeof(pkgCache::VerFile)); + APT_HEADER_SET(DescFileSz, sizeof(pkgCache::DescFile)); +#undef APT_HEADER_SET + GroupCount = 0; PackageCount = 0; VersionCount = 0; DescriptionCount = 0; DependsCount = 0; + DependsDataCount = 0; + ReleaseFileCount = 0; PackageFileCount = 0; VerFileCount = 0; DescFileCount = 0; ProvidesCount = 0; MaxVerFileSize = 0; MaxDescFileSize = 0; - + FileList = 0; -#if APT_PKG_ABI < 413 - APT_IGNORE_DEPRECATED(StringList = 0;) -#endif + RlsFileList = 0; VerSysName = 0; Architecture = 0; SetArchitectures(0); @@ -102,10 +107,12 @@ bool pkgCache::Header::CheckSizes(Header &Against) const if (HeaderSz == Against.HeaderSz && GroupSz == Against.GroupSz && PackageSz == Against.PackageSz && + ReleaseFileSz == Against.ReleaseFileSz && PackageFileSz == Against.PackageFileSz && VersionSz == Against.VersionSz && DescriptionSz == Against.DescriptionSz && DependencySz == Against.DependencySz && + DependencyDataSz == Against.DependencyDataSz && VerFileSz == Against.VerFileSz && DescFileSz == Against.DescFileSz && ProvidesSz == Against.ProvidesSz) @@ -118,7 +125,7 @@ bool pkgCache::Header::CheckSizes(Header &Against) const // --------------------------------------------------------------------- /* */ APT_IGNORE_DEPRECATED_PUSH -pkgCache::pkgCache(MMap *Map, bool DoMap) : Map(*Map) +pkgCache::pkgCache(MMap *Map, bool DoMap) : Map(*Map), d(NULL) { // call getArchitectures() with cached=false to ensure that the // architectures cache is re-evaulated. this is needed in cases @@ -140,11 +147,13 @@ bool pkgCache::ReMap(bool const &Errorchecks) PkgP = (Package *)Map.Data(); VerFileP = (VerFile *)Map.Data(); DescFileP = (DescFile *)Map.Data(); + RlsFileP = (ReleaseFile *)Map.Data(); PkgFileP = (PackageFile *)Map.Data(); VerP = (Version *)Map.Data(); DescP = (Description *)Map.Data(); ProvideP = (Provides *)Map.Data(); DepP = (Dependency *)Map.Data(); + DepDataP = (DependencyData *)Map.Data(); StrP = (char *)Map.Data(); if (Errorchecks == false) @@ -403,10 +412,10 @@ pkgCache::PkgIterator pkgCache::GrpIterator::NextPkg(pkgCache::PkgIterator const return PkgIterator(*Owner, Owner->PkgP + LastPkg->NextPackage); } /*}}}*/ -// GrpIterator::operator ++ - Postfix incr /*{{{*/ +// GrpIterator::operator++ - Prefix incr /*{{{*/ // --------------------------------------------------------------------- /* This will advance to the next logical group in the hash table. */ -void pkgCache::GrpIterator::operator ++(int) +pkgCache::GrpIterator& pkgCache::GrpIterator::operator++() { // Follow the current links if (S != Owner->GrpP) @@ -415,15 +424,16 @@ void pkgCache::GrpIterator::operator ++(int) // Follow the hash table while (S == Owner->GrpP && (HashIndex+1) < (signed)Owner->HeaderP->GetHashTableSize()) { - HashIndex++; + ++HashIndex; S = Owner->GrpP + Owner->HeaderP->GrpHashTableP()[HashIndex]; } + return *this; } /*}}}*/ -// PkgIterator::operator ++ - Postfix incr /*{{{*/ +// PkgIterator::operator++ - Prefix incr /*{{{*/ // --------------------------------------------------------------------- /* This will advance to the next logical package in the hash table. */ -void pkgCache::PkgIterator::operator ++(int) +pkgCache::PkgIterator& pkgCache::PkgIterator::operator++() { // Follow the current links if (S != Owner->PkgP) @@ -432,9 +442,22 @@ void pkgCache::PkgIterator::operator ++(int) // Follow the hash table while (S == Owner->PkgP && (HashIndex+1) < (signed)Owner->HeaderP->GetHashTableSize()) { - HashIndex++; + ++HashIndex; S = Owner->PkgP + Owner->HeaderP->PkgHashTableP()[HashIndex]; } + return *this; +} + /*}}}*/ +pkgCache::DepIterator& pkgCache::DepIterator::operator++() /*{{{*/ +{ + if (S == Owner->DepP) + return *this; + S = Owner->DepP + (Type == DepVer ? S->NextDepends : S->NextRevDepends); + if (S == Owner->DepP) + S2 = Owner->DepDataP; + else + S2 = Owner->DepDataP + S->DependencyData; + return *this; } /*}}}*/ // PkgIterator::State - Check the State of the package /*{{{*/ @@ -536,8 +559,8 @@ std::string pkgCache::PkgIterator::FullName(bool const &Pretty) const bool pkgCache::DepIterator::IsCritical() const { if (IsNegative() == true || - S->Type == pkgCache::Dep::Depends || - S->Type == pkgCache::Dep::PreDepends) + S2->Type == pkgCache::Dep::Depends || + S2->Type == pkgCache::Dep::PreDepends) return true; return false; } @@ -548,9 +571,9 @@ bool pkgCache::DepIterator::IsCritical() const are negative like Conflicts which can and should be handled differently */ bool pkgCache::DepIterator::IsNegative() const { - return S->Type == Dep::DpkgBreaks || - S->Type == Dep::Conflicts || - S->Type == Dep::Obsoletes; + return S2->Type == Dep::DpkgBreaks || + S2->Type == Dep::Conflicts || + S2->Type == Dep::Obsoletes; } /*}}}*/ // DepIterator::SmartTargetPkg - Resolve dep target pointers w/provides /*{{{*/ @@ -679,8 +702,8 @@ void pkgCache::DepIterator::GlobOr(DepIterator &Start,DepIterator &End) End = *this; for (bool LastOR = true; end() == false && LastOR == true;) { - LastOR = (S->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or; - (*this)++; + LastOR = (S2->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or; + ++(*this); if (LastOR == true) End = (*this); } @@ -690,31 +713,22 @@ void pkgCache::DepIterator::GlobOr(DepIterator &Start,DepIterator &End) // --------------------------------------------------------------------- /* Deps like self-conflicts should be ignored as well as implicit conflicts on virtual packages. */ -bool pkgCache::DepIterator::IsIgnorable(PkgIterator const &/*Pkg*/) const +bool pkgCache::DepIterator::IsIgnorable(PkgIterator const &PT) const { if (IsNegative() == false) return false; - pkgCache::PkgIterator PP = ParentPkg(); - pkgCache::PkgIterator PT = TargetPkg(); + pkgCache::PkgIterator const PP = ParentPkg(); if (PP->Group != PT->Group) return false; // self-conflict if (PP == PT) return true; - pkgCache::VerIterator PV = ParentVer(); + pkgCache::VerIterator const PV = ParentVer(); // ignore group-conflict on a M-A:same package - but not our implicit dependencies // so that we can have M-A:same packages conflicting with their own real name if ((PV->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same) - { - // Replaces: ${self}:other ( << ${binary:Version}) - if (S->Type == pkgCache::Dep::Replaces && S->CompareOp == pkgCache::Dep::Less && strcmp(PV.VerStr(), TargetVer()) == 0) - return false; - // Breaks: ${self}:other (!= ${binary:Version}) - if (S->Type == pkgCache::Dep::DpkgBreaks && S->CompareOp == pkgCache::Dep::NotEquals && strcmp(PV.VerStr(), TargetVer()) == 0) - return false; - return true; - } + return IsMultiArchImplicit() == false; return false; } @@ -729,35 +743,34 @@ bool pkgCache::DepIterator::IsIgnorable(PrvIterator const &Prv) const if (Prv.OwnerPkg()->Group == Pkg->Group) return true; // Implicit group-conflicts should not be applied on providers of other groups - if (Pkg->Group == TargetPkg()->Group && Prv.OwnerPkg()->Group != Pkg->Group) + if (IsMultiArchImplicit() && Prv.OwnerPkg()->Group != Pkg->Group) return true; return false; } /*}}}*/ -// DepIterator::IsMultiArchImplicit - added by the cache generation /*{{{*/ -// --------------------------------------------------------------------- -/* MultiArch can be translated to SingleArch for an resolver and we did so, - by adding dependencies to help the resolver understand the problem, but - sometimes it is needed to identify these to ignore them… */ -bool pkgCache::DepIterator::IsMultiArchImplicit() const -{ - if (ParentPkg()->Arch != TargetPkg()->Arch && - (S->Type == pkgCache::Dep::Replaces || - S->Type == pkgCache::Dep::DpkgBreaks || - S->Type == pkgCache::Dep::Conflicts)) - return true; - return false; -} - /*}}}*/ // DepIterator::IsSatisfied - check if a version satisfied the dependency /*{{{*/ bool pkgCache::DepIterator::IsSatisfied(VerIterator const &Ver) const { - return Owner->VS->CheckDep(Ver.VerStr(),S->CompareOp,TargetVer()); + return Owner->VS->CheckDep(Ver.VerStr(),S2->CompareOp,TargetVer()); } bool pkgCache::DepIterator::IsSatisfied(PrvIterator const &Prv) const { - return Owner->VS->CheckDep(Prv.ProvideVersion(),S->CompareOp,TargetVer()); + return Owner->VS->CheckDep(Prv.ProvideVersion(),S2->CompareOp,TargetVer()); +} + /*}}}*/ +// DepIterator::IsImplicit - added by the cache generation /*{{{*/ +bool pkgCache::DepIterator::IsImplicit() const +{ + if (IsMultiArchImplicit() == true) + return true; + if (IsNegative() || S2->Type == pkgCache::Dep::Replaces) + { + if ((S2->CompareOp & pkgCache::Dep::ArchSpecific) != pkgCache::Dep::ArchSpecific && + strcmp(ParentPkg().Arch(), TargetPkg().Arch()) != 0) + return true; + } + return false; } /*}}}*/ // ostream operator to handle string representation of a dependecy /*{{{*/ @@ -814,7 +827,7 @@ APT_PURE bool pkgCache::VerIterator::Downloadable() const { VerFileIterator Files = FileList(); for (; Files.end() == false; ++Files) - if ((Files.File()->Flags & pkgCache::Flag::NotSource) != pkgCache::Flag::NotSource) + if (Files.File().Flagged(pkgCache::Flag::NotSource) == false) return true; return false; } @@ -828,7 +841,7 @@ APT_PURE bool pkgCache::VerIterator::Automatic() const VerFileIterator Files = FileList(); for (; Files.end() == false; ++Files) // Do not check ButAutomaticUpgrades here as it is kind of automatic… - if ((Files.File()->Flags & pkgCache::Flag::NotAutomatic) != pkgCache::Flag::NotAutomatic) + if (Files.File().Flagged(pkgCache::Flag::NotAutomatic) == false) return true; return false; } @@ -854,69 +867,54 @@ pkgCache::VerFileIterator pkgCache::VerIterator::NewestFile() const // --------------------------------------------------------------------- /* This describes the version from a release-centric manner. The output is a list of Label:Version/Archive */ +static std::string PkgFileIteratorToRelString(pkgCache::PkgFileIterator const &File) +{ + std::string Res; + if (File.Label() != 0) + Res = Res + File.Label() + ':'; + + if (File.Archive() != 0) + { + if (File.Version() == 0) + Res += File.Archive(); + else + Res = Res + File.Version() + '/' + File.Archive(); + } + else + { + // No release file, print the host name that this came from + if (File.Site() == 0 || File.Site()[0] == 0) + Res += "localhost"; + else + Res += File.Site(); + } + return Res; +} string pkgCache::VerIterator::RelStr() const { - bool First = true; - string Res; + std::vector<std::string> RelStrs; for (pkgCache::VerFileIterator I = this->FileList(); I.end() == false; ++I) { // Do not print 'not source' entries' - pkgCache::PkgFileIterator File = I.File(); - if ((File->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource) + pkgCache::PkgFileIterator const File = I.File(); + if (File.Flagged(pkgCache::Flag::NotSource)) continue; - // See if we have already printed this out.. - bool Seen = false; - for (pkgCache::VerFileIterator J = this->FileList(); I != J; ++J) - { - pkgCache::PkgFileIterator File2 = J.File(); - if (File2->Label == 0 || File->Label == 0) - continue; - - if (strcmp(File.Label(),File2.Label()) != 0) - continue; - - if (File2->Version == File->Version) - { - Seen = true; - break; - } - if (File2->Version == 0 || File->Version == 0) - break; - if (strcmp(File.Version(),File2.Version()) == 0) - Seen = true; - } - - if (Seen == true) + std::string const RS = PkgFileIteratorToRelString(File); + if (std::find(RelStrs.begin(), RelStrs.end(), RS) != RelStrs.end()) continue; - - if (First == false) - Res += ", "; - else - First = false; - - if (File->Label != 0) - Res = Res + File.Label() + ':'; - if (File->Archive != 0) - { - if (File->Version == 0) - Res += File.Archive(); - else - Res = Res + File.Version() + '/' + File.Archive(); - } - else - { - // No release file, print the host name that this came from - if (File->Site == 0 || File.Site()[0] == 0) - Res += "localhost"; - else - Res += File.Site(); - } + RelStrs.push_back(RS); + } + std::ostringstream os; + if (likely(RelStrs.empty() == false)) + { + std::copy(RelStrs.begin(), RelStrs.end()-1, std::ostream_iterator<std::string>(os, ", ")); + os << *RelStrs.rbegin(); } if (S->ParentPkg != 0) - Res.append(" [").append(Arch()).append("]"); - return Res; + os << " [" << Arch() << "]"; + return os.str(); } /*}}}*/ // VerIterator::MultiArchType - string representing MultiArch flag /*{{{*/ @@ -931,12 +929,12 @@ const char * pkgCache::VerIterator::MultiArchType() const return "none"; } /*}}}*/ -// PkgFileIterator::IsOk - Checks if the cache is in sync with the file /*{{{*/ +// RlsFileIterator::IsOk - Checks if the cache is in sync with the file /*{{{*/ // --------------------------------------------------------------------- /* This stats the file and compares its stats with the ones that were - stored during generation. Date checks should probably also be + stored during generation. Date checks should probably also be included here. */ -bool pkgCache::PkgFileIterator::IsOk() +bool pkgCache::RlsFileIterator::IsOk() { struct stat Buf; if (stat(FileName(),&Buf) != 0) @@ -948,10 +946,8 @@ bool pkgCache::PkgFileIterator::IsOk() return true; } /*}}}*/ -// PkgFileIterator::RelStr - Return the release string /*{{{*/ -// --------------------------------------------------------------------- -/* */ -string pkgCache::PkgFileIterator::RelStr() +// RlsFileIterator::RelStr - Return the release string /*{{{*/ +string pkgCache::RlsFileIterator::RelStr() { string Res; if (Version() != 0) @@ -964,8 +960,40 @@ string pkgCache::PkgFileIterator::RelStr() Res = Res + (Res.empty() == true?"n=":",n=") + Codename(); if (Label() != 0) Res = Res + (Res.empty() == true?"l=":",l=") + Label(); - if (Component() != 0) - Res = Res + (Res.empty() == true?"c=":",c=") + Component(); + return Res; +} + /*}}}*/ +// PkgFileIterator::IsOk - Checks if the cache is in sync with the file /*{{{*/ +// --------------------------------------------------------------------- +/* This stats the file and compares its stats with the ones that were + stored during generation. Date checks should probably also be + included here. */ +bool pkgCache::PkgFileIterator::IsOk() +{ + struct stat Buf; + if (stat(FileName(),&Buf) != 0) + return false; + + if (Buf.st_size != (signed)S->Size || Buf.st_mtime != S->mtime) + return false; + + return true; +} + /*}}}*/ +string pkgCache::PkgFileIterator::RelStr() /*{{{*/ +{ + std::string Res; + if (ReleaseFile() == 0) + { + if (Component() != 0) + Res = Res + (Res.empty() == true?"a=":",a=") + Component(); + } + else + { + Res = ReleaseFile().RelStr(); + if (Component() != 0) + Res = Res + (Res.empty() == true?"c=":",c=") + Component(); + } if (Architecture() != 0) Res = Res + (Res.empty() == true?"b=":",b=") + Architecture(); return Res; @@ -1010,17 +1038,5 @@ pkgCache::DescIterator pkgCache::VerIterator::TranslatedDescription() const } /*}}}*/ -// PrvIterator::IsMultiArchImplicit - added by the cache generation /*{{{*/ -// --------------------------------------------------------------------- -/* MultiArch can be translated to SingleArch for an resolver and we did so, - by adding provides to help the resolver understand the problem, but - sometimes it is needed to identify these to ignore them… */ -bool pkgCache::PrvIterator::IsMultiArchImplicit() const -{ - pkgCache::PkgIterator const Owner = OwnerPkg(); - pkgCache::PkgIterator const Parent = ParentPkg(); - if (strcmp(Owner.Arch(), Parent.Arch()) != 0 || Owner.Group()->Name == Parent.Group()->Name) - return true; - return false; -} - /*}}}*/ + +pkgCache::~pkgCache() {} diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h index 2ba23c5c0..801f8556d 100644 --- a/apt-pkg/pkgcache.h +++ b/apt-pkg/pkgcache.h @@ -85,45 +85,21 @@ using std::string; #endif -#if APT_PKG_ABI >= 413 +// size of (potentially big) files like debs or the install size of them +typedef uint64_t map_filesize_t; // storing file sizes of indexes, which are way below 4 GB for now -typedef uint32_t map_filesize_t; -typedef map_filesize_t should_be_map_filesize_t; -#else -typedef unsigned long map_filesize_t; -typedef unsigned int should_be_map_filesize_t; -#endif -#if APT_PKG_ABI >= 413 +typedef uint32_t map_filesize_small_t; // each package/group/dependency gets an id typedef uint32_t map_id_t; -typedef map_id_t should_be_map_id_t; -#else -typedef unsigned long map_id_t; -typedef unsigned int should_be_map_id_t; -#endif -#if APT_PKG_ABI >= 413 // some files get an id, too, but in far less absolute numbers typedef uint16_t map_fileid_t; -typedef map_fileid_t should_be_map_fileid_t; -#else -typedef unsigned long map_fileid_t; -typedef unsigned int should_be_map_fileid_t; -#endif -#if APT_PKG_ABI >= 413 // relative pointer from cache start typedef uint32_t map_pointer_t; -#else -typedef unsigned int map_pointer_t; -#endif // same as the previous, but documented to be to a string item typedef map_pointer_t map_stringitem_t; -#if APT_PKG_ABI >= 413 -typedef uint64_t should_be_uint64_t; -typedef uint64_t should_be_uint64_small_t; -#else -typedef unsigned long long should_be_uint64_t; -typedef unsigned long should_be_uint64_small_t; -#endif +// we have only a small amount of flags for each item +typedef uint8_t map_flags_t; +typedef uint8_t map_number_t; class pkgVersioningSystem; class pkgCache /*{{{*/ @@ -133,11 +109,13 @@ class pkgCache /*{{{*/ struct Header; struct Group; struct Package; + struct ReleaseFile; struct PackageFile; struct Version; struct Description; struct Provides; struct Dependency; + struct DependencyData; struct StringItem; struct VerFile; struct DescFile; @@ -150,6 +128,7 @@ class pkgCache /*{{{*/ class DescIterator; class DepIterator; class PrvIterator; + class RlsFileIterator; class PkgFileIterator; class VerFileIterator; class DescFileIterator; @@ -170,8 +149,12 @@ class pkgCache /*{{{*/ The lower 4 bits are used to indicate what operator is being specified and the upper 4 bits are flags. OR indicates that the next package is or'd with the current package. */ - enum DepCompareOp {Or=0x10,NoOp=0,LessEq=0x1,GreaterEq=0x2,Less=0x3, - Greater=0x4,Equals=0x5,NotEquals=0x6}; + enum DepCompareOp {NoOp=0,LessEq=0x1,GreaterEq=0x2,Less=0x3, + Greater=0x4,Equals=0x5,NotEquals=0x6, + Or=0x10, /*!< or'ed with the next dependency */ + MultiArchImplicit=0x20, /*!< generated internally, not spelled out in the index */ + ArchSpecific=0x40 /*!< was decorated with an explicit architecture in index */ + }; }; struct State @@ -190,7 +173,19 @@ class pkgCache /*{{{*/ struct Flag { enum PkgFlags {Auto=(1<<0),Essential=(1<<3),Important=(1<<4)}; - enum PkgFFlags {NotSource=(1<<0),NotAutomatic=(1<<1),ButAutomaticUpgrades=(1<<2)}; + enum PkgFFlags { + NotSource=(1<<0), /*!< packages can't be fetched from here, e.g. dpkg/status file */ + LocalSource=(1<<1), /*!< local sources can't and will not be verified by hashes */ + NoPackages=(1<<2), /*!< the file includes no package records itself, but additions like Translations */ + }; + enum ReleaseFileFlags { + NotAutomatic=(1<<0), /*!< archive has a default pin of 1 */ + ButAutomaticUpgrades=(1<<1), /*!< (together with the previous) archive has a default pin of 100 */ + }; + enum ProvidesFlags { + MultiArchImplicit=pkgCache::Dep::MultiArchImplicit, /*!< generated internally, not spelled out in the index */ + ArchSpecific=pkgCache::Dep::ArchSpecific /*!< was decorated with an explicit architecture in index */ + }; }; protected: @@ -210,11 +205,13 @@ class pkgCache /*{{{*/ Package *PkgP; VerFile *VerFileP; DescFile *DescFileP; + ReleaseFile *RlsFileP; PackageFile *PkgFileP; Version *VerP; Description *DescP; Provides *ProvideP; Dependency *DepP; + DependencyData *DepDataP; APT_DEPRECATED StringItem *StringItemP; char *StrP; @@ -228,7 +225,7 @@ class pkgCache /*{{{*/ inline map_id_t Hash(const char *S) const {return sHash(S);} // Useful transformation things - const char *Priority(unsigned char Priority); + static const char *Priority(unsigned char Priority); // Accessors GrpIterator FindGrp(const std::string &Name); @@ -242,6 +239,8 @@ class pkgCache /*{{{*/ inline PkgIterator PkgEnd(); inline PkgFileIterator FileBegin(); inline PkgFileIterator FileEnd(); + inline RlsFileIterator RlsFileBegin(); + inline RlsFileIterator RlsFileEnd(); inline bool MultiArchCache() const { return MultiArchEnabled; } inline char const * NativeArch(); @@ -253,11 +252,12 @@ class pkgCache /*{{{*/ static const char *CompTypeDeb(unsigned char Comp) APT_CONST; static const char *CompType(unsigned char Comp) APT_CONST; static const char *DepType(unsigned char Dep); - + pkgCache(MMap *Map,bool DoMap = true); - virtual ~pkgCache() {} + virtual ~pkgCache(); private: + void * const d; bool MultiArchEnabled; APT_HIDDEN PkgIterator SingleArchFindPkg(const std::string &Name); }; @@ -270,10 +270,10 @@ struct pkgCache::Header This must contain the hex value 0x98FE76DC which is designed to verify that the system loading the image has the same byte order and byte size as the system saving the image */ - unsigned long Signature; + uint32_t Signature; /** These contain the version of the cache file */ - short MajorVersion; - short MinorVersion; + map_number_t MajorVersion; + map_number_t MinorVersion; /** \brief indicates if the cache should be erased Dirty is true if the cache file was opened for reading, the client @@ -288,16 +288,18 @@ struct pkgCache::Header If any of the size values do not exactly match what the client expects then the client should refuse the load the file. */ - unsigned short HeaderSz; - unsigned short GroupSz; - unsigned short PackageSz; - unsigned short PackageFileSz; - unsigned short VersionSz; - unsigned short DescriptionSz; - unsigned short DependencySz; - unsigned short ProvidesSz; - unsigned short VerFileSz; - unsigned short DescFileSz; + uint16_t HeaderSz; + map_number_t GroupSz; + map_number_t PackageSz; + map_number_t ReleaseFileSz; + map_number_t PackageFileSz; + map_number_t VersionSz; + map_number_t DescriptionSz; + map_number_t DependencySz; + map_number_t DependencyDataSz; + map_number_t ProvidesSz; + map_number_t VerFileSz; + map_number_t DescFileSz; /** \brief Structure counts @@ -309,6 +311,8 @@ struct pkgCache::Header map_id_t VersionCount; map_id_t DescriptionCount; map_id_t DependsCount; + map_id_t DependsDataCount; + map_fileid_t ReleaseFileCount; map_fileid_t PackageFileCount; map_fileid_t VerFileCount; map_fileid_t DescFileCount; @@ -319,17 +323,15 @@ struct pkgCache::Header The PackageFile structures are singly linked lists that represent all package files that have been merged into the cache. */ map_pointer_t FileList; -#if APT_PKG_ABI < 413 - APT_DEPRECATED map_pointer_t StringList; -#endif + /** \brief index of the first ReleaseFile structure */ + map_pointer_t RlsFileList; + /** \brief String representing the version system used */ map_pointer_t VerSysName; /** \brief native architecture the cache was built against */ map_pointer_t Architecture; -#if APT_PKG_ABI >= 413 /** \brief all architectures the cache was built against */ map_pointer_t Architectures; -#endif /** \brief The maximum size of a raw entry from the original Package file */ map_filesize_t MaxVerFileSize; /** \brief The maximum size of a raw entry from the original Translation file */ @@ -343,7 +345,7 @@ struct pkgCache::Header the same number of pools as there are structure types. The generator stores this information so future additions can make use of any unused pool blocks. */ - DynamicMMap::Pool Pools[9]; + DynamicMMap::Pool Pools[12]; /** \brief hash tables providing rapid group/package name lookup @@ -355,26 +357,16 @@ struct pkgCache::Header In the PkgHashTable is it possible that multiple packages have the same name - these packages are stored as a sequence in the list. The size of both tables is the same. */ -#if APT_PKG_ABI >= 413 - unsigned int HashTableSize; - unsigned int GetHashTableSize() const { return HashTableSize; } + uint32_t HashTableSize; + uint32_t GetHashTableSize() const { return HashTableSize; } void SetHashTableSize(unsigned int const sz) { HashTableSize = sz; } map_pointer_t GetArchitectures() const { return Architectures; } void SetArchitectures(map_pointer_t const idx) { Architectures = idx; } -#else - // BEWARE: these tables are pretty much empty and just here for abi compat - map_ptrloc PkgHashTable[2*1048]; - map_ptrloc GrpHashTable[2*1048]; - unsigned int GetHashTableSize() const { return PkgHashTable[0]; } - void SetHashTableSize(unsigned int const sz) { PkgHashTable[0] = sz; } - map_pointer_t GetArchitectures() const { return PkgHashTable[1]; } - void SetArchitectures(map_pointer_t const idx) { PkgHashTable[1] = idx; } -#endif map_pointer_t * PkgHashTableP() const { return (map_pointer_t*) (this + 1); } map_pointer_t * GrpHashTableP() const { return PkgHashTableP() + GetHashTableSize(); } /** \brief Size of the complete cache file */ - should_be_uint64_small_t CacheFileSize; + map_filesize_small_t CacheFileSize; bool CheckSizes(Header &Against) const APT_PURE; Header(); @@ -400,7 +392,7 @@ struct pkgCache::Group /** \brief Link to the next Group */ map_pointer_t Next; // Group /** \brief unique sequel ID */ - should_be_map_id_t ID; + map_id_t ID; }; /*}}}*/ @@ -437,12 +429,6 @@ struct pkgCache::Package map_pointer_t VersionList; // Version /** \brief index to the installed version */ map_pointer_t CurrentVer; // Version - /** \brief indicates nothing (consistently) - This field used to contain ONE section the package belongs to, - if those differs between versions it is a RANDOM one. - The Section() method tries to reproduce it, but the only sane - thing to do is use the Section field from the version! */ - APT_DEPRECATED map_ptrloc Section; // StringItem /** \brief index of the group this package belongs to */ map_pointer_t Group; // Group the Package belongs to @@ -456,15 +442,15 @@ struct pkgCache::Package // Install/Remove/Purge etc /** \brief state that the user wishes the package to be in */ - unsigned char SelectedState; // What + map_number_t SelectedState; // What /** \brief installation state of the package This should be "ok" but in case the installation failed it will be different. */ - unsigned char InstState; // Flags + map_number_t InstState; // Flags /** \brief indicates if the package is installed */ - unsigned char CurrentState; // State + map_number_t CurrentState; // State /** \brief unique sequel ID @@ -472,20 +458,19 @@ struct pkgCache::Package This allows clients to create an array of size PackageCount and use it to store state information for the package map. For instance the status file emitter uses this to track which packages have been emitted already. */ - should_be_map_id_t ID; + map_id_t ID; /** \brief some useful indicators of the package's state */ - unsigned long Flags; + map_flags_t Flags; }; /*}}}*/ -// Package File structure /*{{{*/ -/** \brief stores information about the files used to generate the cache +// Release File structure /*{{{*/ +/** \brief stores information about the release files used to generate the cache - Package files are referenced by Version structures to be able to know - after the generation still from which Packages file includes this Version - as we need this information later on e.g. for pinning. */ -struct pkgCache::PackageFile + PackageFiles reference ReleaseFiles as we need to keep record of which + version belongs to which release e.g. for pinning. */ +struct pkgCache::ReleaseFile { - /** \brief physical disk file that this PackageFile represents */ + /** \brief physical disk file that this ReleaseFile represents */ map_stringitem_t FileName; /** \brief the release information @@ -493,13 +478,47 @@ struct pkgCache::PackageFile release information means. */ map_stringitem_t Archive; map_stringitem_t Codename; - map_stringitem_t Component; map_stringitem_t Version; map_stringitem_t Origin; map_stringitem_t Label; - map_stringitem_t Architecture; /** \brief The site the index file was fetched from */ map_stringitem_t Site; + + /** \brief Size of the file + + Used together with the modification time as a + simple check to ensure that the Packages + file has not been altered since Cache generation. */ + map_filesize_t Size; + /** \brief Modification time for the file */ + time_t mtime; + + /** @TODO document PackageFile::Flags */ + map_flags_t Flags; + + // Linked list + /** \brief Link to the next ReleaseFile in the Cache */ + map_pointer_t NextFile; + /** \brief unique sequel ID */ + map_fileid_t ID; +}; + /*}}}*/ +// Package File structure /*{{{*/ +/** \brief stores information about the files used to generate the cache + + Package files are referenced by Version structures to be able to know + after the generation still from which Packages file includes this Version + as we need this information later on e.g. for pinning. */ +struct pkgCache::PackageFile +{ + /** \brief physical disk file that this PackageFile represents */ + map_stringitem_t FileName; + /** \brief the release information */ + map_pointer_t Release; + + map_stringitem_t Component; + map_stringitem_t Architecture; + /** \brief indicates what sort of index file this is @TODO enumerate at least the possible indexes */ @@ -514,13 +533,13 @@ struct pkgCache::PackageFile time_t mtime; /** @TODO document PackageFile::Flags */ - unsigned long Flags; + map_flags_t Flags; // Linked list /** \brief Link to the next PackageFile in the Cache */ map_pointer_t NextFile; // PackageFile /** \brief unique sequel ID */ - should_be_map_fileid_t ID; + map_fileid_t ID; }; /*}}}*/ // VerFile structure /*{{{*/ @@ -535,7 +554,7 @@ struct pkgCache::VerFile /** \brief next step in the linked list */ map_pointer_t NextFile; // PkgVerFile /** \brief position in the package file */ - should_be_map_filesize_t Offset; // File offset + map_filesize_t Offset; // File offset /** @TODO document pkgCache::VerFile::Size */ map_filesize_t Size; }; @@ -549,7 +568,7 @@ struct pkgCache::DescFile /** \brief next step in the linked list */ map_pointer_t NextFile; // PkgVerFile /** \brief position in the file */ - should_be_map_filesize_t Offset; // File offset + map_filesize_t Offset; // File offset /** @TODO document pkgCache::DescFile::Size */ map_filesize_t Size; }; @@ -566,28 +585,30 @@ struct pkgCache::Version map_stringitem_t VerStr; /** \brief section this version is filled in */ map_stringitem_t Section; -#if APT_PKG_ABI >= 413 /** \brief source package name this version comes from Always contains the name, even if it is the same as the binary name */ map_stringitem_t SourcePkgName; /** \brief source version this version comes from Always contains the version string, even if it is the same as the binary version */ map_stringitem_t SourceVerStr; -#endif /** \brief Multi-Arch capabilities of a package version */ - enum VerMultiArch { None = 0, /*!< is the default and doesn't trigger special behaviour */ + enum VerMultiArch { No = 0, /*!< is the default and doesn't trigger special behaviour */ All = (1<<0), /*!< will cause that Ver.Arch() will report "all" */ Foreign = (1<<1), /*!< can satisfy dependencies in another architecture */ Same = (1<<2), /*!< can be co-installed with itself from other architectures */ Allowed = (1<<3), /*!< other packages are allowed to depend on thispkg:any */ AllForeign = All | Foreign, AllAllowed = All | Allowed }; + + /** \brief deprecated variant of No */ + static const APT_DEPRECATED VerMultiArch None = No; + /** \brief stores the MultiArch capabilities of this version Flags used are defined in pkgCache::Version::VerMultiArch */ - unsigned char MultiArch; + map_number_t MultiArch; /** \brief references all the PackageFile's that this version came from @@ -612,18 +633,18 @@ struct pkgCache::Version /** \brief archive size for this version For Debian this is the size of the .deb file. */ - should_be_uint64_t Size; // These are the .deb size + map_filesize_t Size; // These are the .deb size /** \brief uncompressed size for this version */ - should_be_uint64_t InstalledSize; + map_filesize_t InstalledSize; /** \brief characteristic value representing this version No two packages in existence should have the same VerStr and Hash with different contents. */ unsigned short Hash; /** \brief unique sequel ID */ - should_be_map_id_t ID; + map_id_t ID; /** \brief parsed priority value */ - unsigned char Priority; + map_number_t Priority; }; /*}}}*/ // Description structure /*{{{*/ @@ -649,7 +670,7 @@ struct pkgCache::Description map_pointer_t ParentPkg; // Package /** \brief unique sequel ID */ - should_be_map_id_t ID; + map_id_t ID; }; /*}}}*/ // Dependency structure /*{{{*/ @@ -659,7 +680,7 @@ struct pkgCache::Description The base of the linked list is pkgCache::Version::DependsList. All forms of dependencies are recorded here including Depends, Recommends, Suggests, Enhances, Conflicts, Replaces and Breaks. */ -struct pkgCache::Dependency +struct pkgCache::DependencyData { /** \brief string of the version the dependency is applied against */ map_stringitem_t Version; @@ -668,21 +689,28 @@ struct pkgCache::Dependency The generator will - if the package does not already exist - create a blank (no version records) package. */ map_pointer_t Package; // Package - /** \brief next dependency of this version */ - map_pointer_t NextDepends; // Dependency - /** \brief next reverse dependency of this package */ - map_pointer_t NextRevDepends; // Dependency - /** \brief version of the package which has the reverse depends */ - map_pointer_t ParentVer; // Version - /** \brief unique sequel ID */ - should_be_map_id_t ID; /** \brief Dependency type - Depends, Recommends, Conflicts, etc */ - unsigned char Type; + map_number_t Type; /** \brief comparison operator specified on the depends line If the high bit is set then it is a logical OR with the previous record. */ - unsigned char CompareOp; + map_flags_t CompareOp; + + map_pointer_t NextData; +}; +struct pkgCache::Dependency +{ + map_pointer_t DependencyData; // DependencyData + /** \brief version of the package which has the depends */ + map_pointer_t ParentVer; // Version + /** \brief next reverse dependency of this package */ + map_pointer_t NextRevDepends; // Dependency + /** \brief next dependency of this version */ + map_pointer_t NextDepends; // Dependency + + /** \brief unique sequel ID */ + map_id_t ID; }; /*}}}*/ // Provides structure /*{{{*/ @@ -703,9 +731,9 @@ struct pkgCache::Provides /** \brief version in the provides line (if any) This version allows dependencies to depend on specific versions of a - Provides, as well as allowing Provides to override existing packages. - This is experimental. Note that Debian doesn't allow versioned provides */ + Provides, as well as allowing Provides to override existing packages. */ map_stringitem_t ProvideVersion; + map_flags_t Flags; /** \brief next provides (based of package) */ map_pointer_t NextProvides; // Provides /** \brief next provides (based of version) */ @@ -739,6 +767,11 @@ inline pkgCache::PkgFileIterator pkgCache::FileBegin() {return PkgFileIterator(*this,PkgFileP + HeaderP->FileList);} inline pkgCache::PkgFileIterator pkgCache::FileEnd() {return PkgFileIterator(*this,PkgFileP);} +inline pkgCache::RlsFileIterator pkgCache::RlsFileBegin() + {return RlsFileIterator(*this,RlsFileP + HeaderP->RlsFileList);} +inline pkgCache::RlsFileIterator pkgCache::RlsFileEnd() + {return RlsFileIterator(*this,RlsFileP);} + // Oh I wish for Real Name Space Support class pkgCache::Namespace /*{{{*/ @@ -750,6 +783,7 @@ class pkgCache::Namespace /*{{{*/ typedef pkgCache::DescIterator DescIterator; typedef pkgCache::DepIterator DepIterator; typedef pkgCache::PrvIterator PrvIterator; + typedef pkgCache::RlsFileIterator RlsFileIterator; typedef pkgCache::PkgFileIterator PkgFileIterator; typedef pkgCache::VerFileIterator VerFileIterator; typedef pkgCache::Version Version; diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index ba454f057..6daebbc2a 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -18,8 +18,6 @@ #include <apt-pkg/progress.h> #include <apt-pkg/sourcelist.h> #include <apt-pkg/configuration.h> -#include <apt-pkg/strutl.h> -#include <apt-pkg/sptr.h> #include <apt-pkg/pkgsystem.h> #include <apt-pkg/macros.h> #include <apt-pkg/metaindex.h> @@ -36,11 +34,14 @@ #include <iostream> #include <string> #include <vector> +#include <memory> +#include <algorithm> #include <sys/stat.h> #include <unistd.h> #include <apti18n.h> - /*}}}*/ + +template<class T> using Dynamic = pkgCacheGenerator::Dynamic<T>; /*}}}*/ typedef std::vector<pkgIndexFile *>::iterator FileIterator; template <typename Iter> std::vector<Iter*> pkgCacheGenerator::Dynamic<Iter>::toReMap; @@ -54,10 +55,8 @@ using std::string; /* We set the dirty flag and make sure that is written to the disk */ pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) : Map(*pMap), Cache(pMap,false), Progress(Prog), - FoundFileDeps(0) + CurrentRlsFile(NULL), CurrentFile(NULL), d(NULL) { - CurrentFile = 0; - if (_error->PendingError() == true) return; @@ -145,6 +144,7 @@ void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newM Cache.ReMap(false); CurrentFile += (pkgCache::PackageFile const * const) newMap - (pkgCache::PackageFile const * const) oldMap; + CurrentRlsFile += (pkgCache::ReleaseFile const * const) newMap - (pkgCache::ReleaseFile const * const) oldMap; for (std::vector<pkgCache::GrpIterator*>::const_iterator i = Dynamic<pkgCache::GrpIterator>::toReMap.begin(); i != Dynamic<pkgCache::GrpIterator>::toReMap.end(); ++i) @@ -167,6 +167,9 @@ void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newM for (std::vector<pkgCache::PkgFileIterator*>::const_iterator i = Dynamic<pkgCache::PkgFileIterator>::toReMap.begin(); i != Dynamic<pkgCache::PkgFileIterator>::toReMap.end(); ++i) (*i)->ReMap(oldMap, newMap); + for (std::vector<pkgCache::RlsFileIterator*>::const_iterator i = Dynamic<pkgCache::RlsFileIterator>::toReMap.begin(); + i != Dynamic<pkgCache::RlsFileIterator>::toReMap.end(); ++i) + (*i)->ReMap(oldMap, newMap); } /*}}}*/ // CacheGenerator::WriteStringInMap /*{{{*/ map_stringitem_t pkgCacheGenerator::WriteStringInMap(const char *String, @@ -225,22 +228,6 @@ bool pkgCacheGenerator::MergeList(ListParser &List, continue; } - if (Arch.empty() == true) - { - // use the pseudo arch 'none' for arch-less packages - Arch = "none"; - /* We might built a SingleArchCache here, which we don't want to blow up - just for these :none packages to a proper MultiArchCache, so just ensure - that we have always a native package structure first for SingleArch */ - pkgCache::PkgIterator NP; - Dynamic<pkgCache::PkgIterator> DynPkg(NP); - if (NewPackage(NP, PackageName, _config->Find("APT::Architecture")) == false) - // TRANSLATOR: The first placeholder is a package name, - // the other two should be copied verbatim as they include debug info - return _error->Error(_("Error occurred while processing %s (%s%d)"), - PackageName.c_str(), "NewPackage", 0); - } - // Get a pointer to the package structure pkgCache::PkgIterator Pkg; Dynamic<pkgCache::PkgIterator> DynPkg(Pkg); @@ -263,10 +250,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List, } if (OutVer != 0) - { - FoundFileDeps |= List.HasFileDeps(); return true; - } } if (Cache.HeaderP->PackageCount >= std::numeric_limits<map_id_t>::max()) @@ -282,7 +266,6 @@ bool pkgCacheGenerator::MergeList(ListParser &List, return _error->Error(_("Wow, you exceeded the number of dependencies " "this APT is capable of.")); - FoundFileDeps |= List.HasFileDeps(); return true; } // CacheGenerator::MergeListGroup /*{{{*/ @@ -440,40 +423,6 @@ bool pkgCacheGenerator::MergeListVersion(ListParser &List, pkgCache::PkgIterator return _error->Error(_("Error occurred while processing %s (%s%d)"), Pkg.Name(), "AddImplicitDepends", 1); } - /* :none packages are packages without an architecture. They are forbidden by - debian-policy, so usually they will only be in (old) dpkg status files - - and dpkg will complain about them - and are pretty rare. We therefore do - usually not create conflicts while the parent is created, but only if a :none - package (= the target) appears. This creates incorrect dependencies on :none - for architecture-specific dependencies on the package we copy from, but we - will ignore this bug as architecture-specific dependencies are only allowed - in jessie and until then the :none packages should be extinct (hopefully). - In other words: This should work long enough to allow graceful removal of - these packages, it is not supposed to allow users to keep using them … */ - if (strcmp(Pkg.Arch(), "none") == 0) - { - pkgCache::PkgIterator M = Grp.FindPreferredPkg(); - if (M.end() == false && Pkg != M) - { - pkgCache::DepIterator D = M.RevDependsList(); - Dynamic<pkgCache::DepIterator> DynD(D); - for (; D.end() == false; ++D) - { - if ((D->Type != pkgCache::Dep::Conflicts && - D->Type != pkgCache::Dep::DpkgBreaks && - D->Type != pkgCache::Dep::Replaces) || - D.ParentPkg().Group() == Grp) - continue; - - map_pointer_t *OldDepLast = NULL; - pkgCache::VerIterator ConVersion = D.ParentVer(); - Dynamic<pkgCache::VerIterator> DynV(ConVersion); - // duplicate the Conflicts/Breaks/Replaces for :none arch - NewDepends(Pkg, ConVersion, D->Version, - D->CompareOp, D->Type, OldDepLast); - } - } - } } if (unlikely(AddImplicitDepends(Grp, Pkg, Ver) == false)) return _error->Error(_("Error occurred while processing %s (%s%d)"), @@ -543,57 +492,6 @@ bool pkgCacheGenerator::AddNewDescription(ListParser &List, pkgCache::VerIterato } /*}}}*/ /*}}}*/ -// CacheGenerator::MergeFileProvides - Merge file provides /*{{{*/ -// --------------------------------------------------------------------- -/* If we found any file depends while parsing the main list we need to - resolve them. Since it is undesired to load the entire list of files - into the cache as virtual packages we do a two stage effort. MergeList - identifies the file depends and this creates Provdies for them by - re-parsing all the indexs. */ -bool pkgCacheGenerator::MergeFileProvides(ListParser &List) -{ - List.Owner = this; - - unsigned int Counter = 0; - while (List.Step() == true) - { - string PackageName = List.Package(); - if (PackageName.empty() == true) - return false; - string Version = List.Version(); - if (Version.empty() == true) - continue; - - pkgCache::PkgIterator Pkg = Cache.FindPkg(PackageName); - Dynamic<pkgCache::PkgIterator> DynPkg(Pkg); - if (Pkg.end() == true) - return _error->Error(_("Error occurred while processing %s (%s%d)"), - PackageName.c_str(), "FindPkg", 1); - Counter++; - if (Counter % 100 == 0 && Progress != 0) - Progress->Progress(List.Offset()); - - unsigned short Hash = List.VersionHash(); - pkgCache::VerIterator Ver = Pkg.VersionList(); - Dynamic<pkgCache::VerIterator> DynVer(Ver); - for (; Ver.end() == false; ++Ver) - { - if (List.SameVersion(Hash, Ver) == true && Version == Ver.VerStr()) - { - if (List.CollectFileProvides(Cache,Ver) == false) - return _error->Error(_("Error occurred while processing %s (%s%d)"), - PackageName.c_str(), "CollectFileProvides", 1); - break; - } - } - - if (Ver.end() == true) - _error->Warning(_("Package %s %s was not found while processing file dependencies"),PackageName.c_str(),Version.c_str()); - } - - return true; -} - /*}}}*/ // CacheGenerator::NewGroup - Add a new group /*{{{*/ // --------------------------------------------------------------------- /* This creates a new group structure and adds it to the hash table */ @@ -646,6 +544,16 @@ bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name return false; Pkg = pkgCache::PkgIterator(Cache,Cache.PkgP + Package); + // Set the name, arch and the ID + APT_IGNORE_DEPRECATED(Pkg->Name = Grp->Name;) + Pkg->Group = Grp.Index(); + // all is mapped to the native architecture + map_stringitem_t const idxArch = (Arch == "all") ? Cache.HeaderP->Architecture : StoreString(MIXED, Arch); + if (unlikely(idxArch == 0)) + return false; + Pkg->Arch = idxArch; + Pkg->ID = Cache.HeaderP->PackageCount++; + // Insert the package into our package list if (Grp->FirstPackage == 0) // the group is new { @@ -660,23 +568,53 @@ bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name } else // Group the Packages together { + // but first get implicit provides done + if (APT::Configuration::checkArchitecture(Pkg.Arch()) == true) + { + pkgCache::PkgIterator const M = Grp.FindPreferredPkg(false); // native or any foreign pkg will do + if (M.end() == false) + for (pkgCache::PrvIterator Prv = M.ProvidesList(); Prv.end() == false; ++Prv) + { + if ((Prv->Flags & pkgCache::Flag::ArchSpecific) != 0) + continue; + pkgCache::VerIterator Ver = Prv.OwnerVer(); + if ((Ver->MultiArch & pkgCache::Version::Allowed) == pkgCache::Version::Allowed || + ((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign && + (Prv->Flags & pkgCache::Flag::MultiArchImplicit) == 0)) + if (NewProvides(Ver, Pkg, Prv->ProvideVersion, Prv->Flags) == false) + return false; + } + + for (pkgCache::PkgIterator P = Grp.PackageList(); P.end() == false; P = Grp.NextPkg(P)) + for (pkgCache::VerIterator Ver = P.VersionList(); Ver.end() == false; ++Ver) + if ((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign) + if (NewProvides(Ver, Pkg, Ver->VerStr, pkgCache::Flag::MultiArchImplicit) == false) + return false; + } + // and negative dependencies, don't forget negative dependencies + { + pkgCache::PkgIterator const M = Grp.FindPreferredPkg(false); + if (M.end() == false) + for (pkgCache::DepIterator Dep = M.RevDependsList(); Dep.end() == false; ++Dep) + { + if ((Dep->CompareOp & (pkgCache::Dep::ArchSpecific | pkgCache::Dep::MultiArchImplicit)) != 0) + continue; + if (Dep->Type != pkgCache::Dep::DpkgBreaks && Dep->Type != pkgCache::Dep::Conflicts && + Dep->Type != pkgCache::Dep::Replaces) + continue; + pkgCache::VerIterator Ver = Dep.ParentVer(); + map_pointer_t * unused = NULL; + if (NewDepends(Pkg, Ver, Dep->Version, Dep->CompareOp, Dep->Type, unused) == false) + return false; + } + } + // this package is the new last package pkgCache::PkgIterator LastPkg(Cache, Cache.PkgP + Grp->LastPackage); Pkg->NextPackage = LastPkg->NextPackage; LastPkg->NextPackage = Package; } Grp->LastPackage = Package; - - // Set the name, arch and the ID - APT_IGNORE_DEPRECATED(Pkg->Name = Grp->Name;) - Pkg->Group = Grp.Index(); - // all is mapped to the native architecture - map_stringitem_t const idxArch = (Arch == "all") ? Cache.HeaderP->Architecture : StoreString(MIXED, Arch); - if (unlikely(idxArch == 0)) - return false; - Pkg->Arch = idxArch; - Pkg->ID = Cache.HeaderP->PackageCount++; - return true; } /*}}}*/ @@ -707,16 +645,16 @@ bool pkgCacheGenerator::AddImplicitDepends(pkgCache::GrpIterator &G, { // Replaces: ${self}:other ( << ${binary:Version}) NewDepends(D, V, VerStrIdx, - pkgCache::Dep::Less, pkgCache::Dep::Replaces, + pkgCache::Dep::Less | pkgCache::Dep::MultiArchImplicit, pkgCache::Dep::Replaces, OldDepLast); // Breaks: ${self}:other (!= ${binary:Version}) NewDepends(D, V, VerStrIdx, - pkgCache::Dep::NotEquals, pkgCache::Dep::DpkgBreaks, + pkgCache::Dep::NotEquals | pkgCache::Dep::MultiArchImplicit, pkgCache::Dep::DpkgBreaks, OldDepLast); } else { // Conflicts: ${self}:other NewDepends(D, V, 0, - pkgCache::Dep::NoOp, pkgCache::Dep::Conflicts, + pkgCache::Dep::NoOp | pkgCache::Dep::MultiArchImplicit, pkgCache::Dep::Conflicts, OldDepLast); } } @@ -735,16 +673,16 @@ bool pkgCacheGenerator::AddImplicitDepends(pkgCache::VerIterator &V, map_stringitem_t const VerStrIdx = V->VerStr; // Replaces: ${self}:other ( << ${binary:Version}) NewDepends(D, V, VerStrIdx, - pkgCache::Dep::Less, pkgCache::Dep::Replaces, + pkgCache::Dep::Less | pkgCache::Dep::MultiArchImplicit, pkgCache::Dep::Replaces, OldDepLast); // Breaks: ${self}:other (!= ${binary:Version}) NewDepends(D, V, VerStrIdx, - pkgCache::Dep::NotEquals, pkgCache::Dep::DpkgBreaks, + pkgCache::Dep::NotEquals | pkgCache::Dep::MultiArchImplicit, pkgCache::Dep::DpkgBreaks, OldDepLast); } else { // Conflicts: ${self}:other NewDepends(D, V, 0, - pkgCache::Dep::NoOp, pkgCache::Dep::Conflicts, + pkgCache::Dep::NoOp | pkgCache::Dep::MultiArchImplicit, pkgCache::Dep::Conflicts, OldDepLast); } return true; @@ -910,36 +848,9 @@ map_pointer_t pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc, version and to the package that it is pointing to. */ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver, - string const &Version, - unsigned int const &Op, - unsigned int const &Type, - map_stringitem_t* &OldDepLast) -{ - map_stringitem_t index = 0; - if (Version.empty() == false) - { - int const CmpOp = Op & 0x0F; - // =-deps are used (79:1) for lockstep on same-source packages (e.g. data-packages) - if (CmpOp == pkgCache::Dep::Equals && strcmp(Version.c_str(), Ver.VerStr()) == 0) - index = Ver->VerStr; - - if (index == 0) - { - void const * const oldMap = Map.Data(); - index = StoreString(VERSIONNUMBER, Version); - if (unlikely(index == 0)) - return false; - if (OldDepLast != 0 && oldMap != Map.Data()) - OldDepLast += (map_pointer_t const * const) Map.Data() - (map_pointer_t const * const) oldMap; - } - } - return NewDepends(Pkg, Ver, index, Op, Type, OldDepLast); -} -bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg, - pkgCache::VerIterator &Ver, map_pointer_t const Version, - unsigned int const &Op, - unsigned int const &Type, + uint8_t const Op, + uint8_t const Type, map_pointer_t* &OldDepLast) { void const * const oldMap = Map.Data(); @@ -948,19 +859,72 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg, if (unlikely(Dependency == 0)) return false; - // Fill it in - pkgCache::DepIterator Dep(Cache,Cache.DepP + Dependency); - Dynamic<pkgCache::DepIterator> DynDep(Dep); - Dep->ParentVer = Ver.Index(); - Dep->Type = Type; - Dep->CompareOp = Op; - Dep->Version = Version; - Dep->ID = Cache.HeaderP->DependsCount++; + bool isDuplicate = false; + map_pointer_t DependencyData = 0; + map_pointer_t PreviousData = 0; + if (Pkg->RevDepends != 0) + { + pkgCache::Dependency const * const L = Cache.DepP + Pkg->RevDepends; + DependencyData = L->DependencyData; + do { + pkgCache::DependencyData const * const D = Cache.DepDataP + DependencyData; + if (Version > D->Version) + break; + if (D->Version == Version && D->Type == Type && D->CompareOp == Op) + { + isDuplicate = true; + break; + } + PreviousData = DependencyData; + DependencyData = D->NextData; + } while (DependencyData != 0); + } + + if (isDuplicate == false) + { + DependencyData = AllocateInMap(sizeof(pkgCache::DependencyData)); + if (unlikely(DependencyData == 0)) + return false; + } + + pkgCache::Dependency * Link = Cache.DepP + Dependency; + Link->ParentVer = Ver.Index(); + Link->DependencyData = DependencyData; + Link->ID = Cache.HeaderP->DependsCount++; + + pkgCache::DepIterator Dep(Cache, Link); + if (isDuplicate == false) + { + Dep->Type = Type; + Dep->CompareOp = Op; + Dep->Version = Version; + Dep->Package = Pkg.Index(); + ++Cache.HeaderP->DependsDataCount; + if (PreviousData != 0) + { + pkgCache::DependencyData * const D = Cache.DepDataP + PreviousData; + Dep->NextData = D->NextData; + D->NextData = DependencyData; + } + else if (Pkg->RevDepends != 0) + { + pkgCache::Dependency const * const D = Cache.DepP + Pkg->RevDepends; + Dep->NextData = D->DependencyData; + } + } + + if (isDuplicate == true || PreviousData != 0) + { + pkgCache::Dependency * const L = Cache.DepP + Pkg->RevDepends; + Link->NextRevDepends = L->NextRevDepends; + L->NextRevDepends = Dependency; + } + else + { + Link->NextRevDepends = Pkg->RevDepends; + Pkg->RevDepends = Dependency; + } - // Link it to the package - Dep->Package = Pkg.Index(); - Dep->NextRevDepends = Pkg->RevDepends; - Pkg->RevDepends = Dep.Index(); // Do we know where to link the Dependency to? if (OldDepLast == NULL) @@ -972,9 +936,8 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg, OldDepLast += (map_pointer_t const * const) Map.Data() - (map_pointer_t const * const) oldMap; Dep->NextDepends = *OldDepLast; - *OldDepLast = Dep.Index(); + *OldDepLast = Dependency; OldDepLast = &Dep->NextDepends; - return true; } /*}}}*/ @@ -982,103 +945,208 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg, // --------------------------------------------------------------------- /* This creates a Group and the Package to link this dependency to if needed and handles also the caching of the old endpoint */ -bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver, +bool pkgCacheListParser::NewDepends(pkgCache::VerIterator &Ver, const string &PackageName, const string &Arch, const string &Version, - unsigned int Op, - unsigned int Type) + uint8_t const Op, + uint8_t const Type) { pkgCache::GrpIterator Grp; Dynamic<pkgCache::GrpIterator> DynGrp(Grp); if (unlikely(Owner->NewGroup(Grp, PackageName) == false)) return false; - // Locate the target package - pkgCache::PkgIterator Pkg = Grp.FindPkg(Arch); - // we don't create 'none' packages and their dependencies if we can avoid it … - if (Pkg.end() == true && Arch == "none" && strcmp(Ver.ParentPkg().Arch(), "none") != 0) - return true; - Dynamic<pkgCache::PkgIterator> DynPkg(Pkg); - if (Pkg.end() == true) { - if (unlikely(Owner->NewPackage(Pkg, PackageName, Arch) == false)) - return false; + map_stringitem_t idxVersion = 0; + if (Version.empty() == false) + { + int const CmpOp = Op & 0x0F; + // =-deps are used (79:1) for lockstep on same-source packages (e.g. data-packages) + if (CmpOp == pkgCache::Dep::Equals && strcmp(Version.c_str(), Ver.VerStr()) == 0) + idxVersion = Ver->VerStr; + + if (idxVersion == 0) + { + idxVersion = StoreString(pkgCacheGenerator::VERSIONNUMBER, Version); + if (unlikely(idxVersion == 0)) + return false; + } } - // Is it a file dependency? - if (unlikely(PackageName[0] == '/')) - FoundFileDeps = true; + bool const isNegative = (Type == pkgCache::Dep::DpkgBreaks || + Type == pkgCache::Dep::Conflicts || + Type == pkgCache::Dep::Replaces); - /* Caching the old end point speeds up generation substantially */ - if (OldDepVer != Ver) { - OldDepLast = NULL; - OldDepVer = Ver; + pkgCache::PkgIterator Pkg; + Dynamic<pkgCache::PkgIterator> DynPkg(Pkg); + if (isNegative == false || (Op & pkgCache::Dep::ArchSpecific) == pkgCache::Dep::ArchSpecific || Grp->FirstPackage == 0) + { + // Locate the target package + Pkg = Grp.FindPkg(Arch); + if (Pkg.end() == true) { + if (unlikely(Owner->NewPackage(Pkg, PackageName, Arch) == false)) + return false; + } + + /* Caching the old end point speeds up generation substantially */ + if (OldDepVer != Ver) { + OldDepLast = NULL; + OldDepVer = Ver; + } + + return Owner->NewDepends(Pkg, Ver, idxVersion, Op, Type, OldDepLast); } + else + { + /* Caching the old end point speeds up generation substantially */ + if (OldDepVer != Ver) { + OldDepLast = NULL; + OldDepVer = Ver; + } - return Owner->NewDepends(Pkg, Ver, Version, Op, Type, OldDepLast); + for (Pkg = Grp.PackageList(); Pkg.end() == false; Pkg = Grp.NextPkg(Pkg)) + { + if (Owner->NewDepends(Pkg, Ver, idxVersion, Op, Type, OldDepLast) == false) + return false; + } + } + return true; } /*}}}*/ // ListParser::NewProvides - Create a Provides element /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator &Ver, - const string &PkgName, +bool pkgCacheListParser::NewProvides(pkgCache::VerIterator &Ver, + const string &PkgName, const string &PkgArch, - const string &Version) + const string &Version, + uint8_t const Flags) { - pkgCache &Cache = Owner->Cache; + pkgCache const &Cache = Owner->Cache; // We do not add self referencing provides if (Ver.ParentPkg().Name() == PkgName && (PkgArch == Ver.ParentPkg().Arch() || (PkgArch == "all" && strcmp((Cache.StrP + Cache.HeaderP->Architecture), Ver.ParentPkg().Arch()) == 0))) return true; - + + // Locate the target package + pkgCache::PkgIterator Pkg; + Dynamic<pkgCache::PkgIterator> DynPkg(Pkg); + if (unlikely(Owner->NewPackage(Pkg,PkgName, PkgArch) == false)) + return false; + + map_stringitem_t idxProvideVersion = 0; + if (Version.empty() == false) { + idxProvideVersion = StoreString(pkgCacheGenerator::VERSIONNUMBER, Version); + if (unlikely(idxProvideVersion == 0)) + return false; + } + return Owner->NewProvides(Ver, Pkg, idxProvideVersion, Flags); +} +bool pkgCacheGenerator::NewProvides(pkgCache::VerIterator &Ver, + pkgCache::PkgIterator &Pkg, + map_pointer_t const ProvideVersion, + uint8_t const Flags) +{ // Get a structure - map_pointer_t const Provides = Owner->AllocateInMap(sizeof(pkgCache::Provides)); + map_pointer_t const Provides = AllocateInMap(sizeof(pkgCache::Provides)); if (unlikely(Provides == 0)) return false; - Cache.HeaderP->ProvidesCount++; - + ++Cache.HeaderP->ProvidesCount; + // Fill it in pkgCache::PrvIterator Prv(Cache,Cache.ProvideP + Provides,Cache.PkgP); - Dynamic<pkgCache::PrvIterator> DynPrv(Prv); Prv->Version = Ver.Index(); + Prv->ProvideVersion = ProvideVersion; + Prv->Flags = Flags; Prv->NextPkgProv = Ver->ProvidesList; Ver->ProvidesList = Prv.Index(); - if (Version.empty() == false) { - map_stringitem_t const idxProvideVersion = WriteString(Version); - Prv->ProvideVersion = idxProvideVersion; - if (unlikely(idxProvideVersion == 0)) - return false; - } - - // Locate the target package - pkgCache::PkgIterator Pkg; - Dynamic<pkgCache::PkgIterator> DynPkg(Pkg); - if (unlikely(Owner->NewPackage(Pkg,PkgName, PkgArch) == false)) - return false; - + // Link it to the package Prv->ParentPkg = Pkg.Index(); Prv->NextProvides = Pkg->ProvidesList; Pkg->ProvidesList = Prv.Index(); - return true; } /*}}}*/ -bool pkgCacheGenerator::ListParser::SameVersion(unsigned short const Hash,/*{{{*/ +// ListParser::NewProvidesAllArch - add provides for all architectures /*{{{*/ +bool pkgCacheListParser::NewProvidesAllArch(pkgCache::VerIterator &Ver, string const &Package, + string const &Version, uint8_t const Flags) { + pkgCache &Cache = Owner->Cache; + pkgCache::GrpIterator const Grp = Cache.FindGrp(Package); + if (Grp.end() == true) + return NewProvides(Ver, Package, Cache.NativeArch(), Version, Flags); + else + { + map_stringitem_t idxProvideVersion = 0; + if (Version.empty() == false) { + idxProvideVersion = StoreString(pkgCacheGenerator::VERSIONNUMBER, Version); + if (unlikely(idxProvideVersion == 0)) + return false; + } + + bool const isImplicit = (Flags & pkgCache::Flag::MultiArchImplicit) == pkgCache::Flag::MultiArchImplicit; + bool const isArchSpecific = (Flags & pkgCache::Flag::ArchSpecific) == pkgCache::Flag::ArchSpecific; + pkgCache::PkgIterator const OwnerPkg = Ver.ParentPkg(); + for (pkgCache::PkgIterator Pkg = Grp.PackageList(); Pkg.end() == false; Pkg = Grp.NextPkg(Pkg)) + { + if (isImplicit && OwnerPkg == Pkg) + continue; + if (isArchSpecific == false && APT::Configuration::checkArchitecture(OwnerPkg.Arch()) == false) + continue; + if (Owner->NewProvides(Ver, Pkg, idxProvideVersion, Flags) == false) + return false; + } + } + return true; +} + /*}}}*/ +bool pkgCacheListParser::SameVersion(unsigned short const Hash, /*{{{*/ pkgCache::VerIterator const &Ver) { return Hash == Ver->Hash; } /*}}}*/ +// CacheGenerator::SelectReleaseFile - Select the current release file the indexes belong to /*{{{*/ +bool pkgCacheGenerator::SelectReleaseFile(const string &File,const string &Site, + unsigned long Flags) +{ + if (File.empty() && Site.empty()) + { + CurrentRlsFile = NULL; + return true; + } + + // Get some space for the structure + map_pointer_t const idxFile = AllocateInMap(sizeof(*CurrentRlsFile)); + if (unlikely(idxFile == 0)) + return false; + CurrentRlsFile = Cache.RlsFileP + idxFile; + + // Fill it in + map_stringitem_t const idxFileName = WriteStringInMap(File); + map_stringitem_t const idxSite = StoreString(MIXED, Site); + if (unlikely(idxFileName == 0 || idxSite == 0)) + return false; + CurrentRlsFile->FileName = idxFileName; + CurrentRlsFile->Site = idxSite; + CurrentRlsFile->NextFile = Cache.HeaderP->RlsFileList; + CurrentRlsFile->Flags = Flags; + CurrentRlsFile->ID = Cache.HeaderP->ReleaseFileCount; + RlsFileName = File; + Cache.HeaderP->RlsFileList = CurrentRlsFile - Cache.RlsFileP; + Cache.HeaderP->ReleaseFileCount++; + + return true; +} + /*}}}*/ // CacheGenerator::SelectFile - Select the current file being parsed /*{{{*/ // --------------------------------------------------------------------- /* This is used to select which file is to be associated with all newly added versions. The caller is responsible for setting the IMS fields. */ -bool pkgCacheGenerator::SelectFile(const string &File,const string &Site, - const pkgIndexFile &Index, - unsigned long Flags) +bool pkgCacheGenerator::SelectFile(std::string const &File, + pkgIndexFile const &Index, + std::string const &Architecture, + std::string const &Component, + unsigned long const Flags) { // Get some space for the structure map_pointer_t const idxFile = AllocateInMap(sizeof(*CurrentFile)); @@ -1088,18 +1156,33 @@ bool pkgCacheGenerator::SelectFile(const string &File,const string &Site, // Fill it in map_stringitem_t const idxFileName = WriteStringInMap(File); - map_stringitem_t const idxSite = StoreString(MIXED, Site); - if (unlikely(idxFileName == 0 || idxSite == 0)) + if (unlikely(idxFileName == 0)) return false; CurrentFile->FileName = idxFileName; - CurrentFile->Site = idxSite; CurrentFile->NextFile = Cache.HeaderP->FileList; - CurrentFile->Flags = Flags; CurrentFile->ID = Cache.HeaderP->PackageFileCount; map_stringitem_t const idxIndexType = StoreString(MIXED, Index.GetType()->Label); if (unlikely(idxIndexType == 0)) return false; CurrentFile->IndexType = idxIndexType; + if (Architecture.empty()) + CurrentFile->Architecture = 0; + else + { + map_stringitem_t const arch = StoreString(pkgCacheGenerator::MIXED, Architecture); + if (unlikely(arch == 0)) + return false; + CurrentFile->Architecture = arch; + } + map_stringitem_t const component = StoreString(pkgCacheGenerator::MIXED, Component); + if (unlikely(component == 0)) + return false; + CurrentFile->Component = component; + CurrentFile->Flags = Flags; + if (CurrentRlsFile != NULL) + CurrentFile->Release = CurrentRlsFile - Cache.RlsFileP; + else + CurrentFile->Release = 0; PkgFileName = File; Cache.HeaderP->FileList = CurrentFile - Cache.PkgFileP; Cache.HeaderP->PackageFileCount++; @@ -1141,10 +1224,10 @@ map_stringitem_t pkgCacheGenerator::StoreString(enum StringType const type, cons /* This just verifies that each file in the list of index files exists, has matching attributes with the cache and the cache does not have any extra files. */ -static bool CheckValidity(const string &CacheFile, +static bool CheckValidity(const string &CacheFile, pkgSourceList &List, - FileIterator Start, - FileIterator End, + FileIterator const Start, + FileIterator const End, MMap **OutMap = 0) { bool const Debug = _config->FindB("Debug::pkgCacheGen", false); @@ -1152,7 +1235,7 @@ static bool CheckValidity(const string &CacheFile, if (CacheFile.empty() == true || FileExists(CacheFile) == false) { if (Debug == true) - std::clog << "CacheFile doesn't exist" << std::endl; + std::clog << "CacheFile " << CacheFile << " doesn't exist" << std::endl; return false; } @@ -1165,44 +1248,66 @@ static bool CheckValidity(const string &CacheFile, // Map it FileFd CacheF(CacheFile,FileFd::ReadOnly); - SPtr<MMap> Map = new MMap(CacheF,0); - pkgCache Cache(Map); + std::unique_ptr<MMap> Map(new MMap(CacheF,0)); + pkgCache Cache(Map.get()); if (_error->PendingError() == true || Map->Size() == 0) { if (Debug == true) - std::clog << "Errors are pending or Map is empty()" << std::endl; + std::clog << "Errors are pending or Map is empty() for " << CacheFile << std::endl; _error->Discard(); return false; } - - /* Now we check every index file, see if it is in the cache, - verify the IMS data and check that it is on the disk too.. */ - SPtrArray<bool> Visited = new bool[Cache.HeaderP->PackageFileCount]; - memset(Visited,0,sizeof(*Visited)*Cache.HeaderP->PackageFileCount); - for (; Start != End; ++Start) + + std::unique_ptr<bool[]> RlsVisited(new bool[Cache.HeaderP->ReleaseFileCount]); + memset(RlsVisited.get(),0,sizeof(RlsVisited[0])*Cache.HeaderP->ReleaseFileCount); + std::vector<pkgIndexFile *> Files; + for (pkgSourceList::const_iterator i = List.begin(); i != List.end(); ++i) { if (Debug == true) - std::clog << "Checking PkgFile " << (*Start)->Describe() << ": "; - if ((*Start)->HasPackages() == false) + std::clog << "Checking RlsFile " << (*i)->Describe() << ": "; + pkgCache::RlsFileIterator const RlsFile = (*i)->FindInCache(Cache, true); + if (RlsFile.end() == true) { - if (Debug == true) - std::clog << "Has NO packages" << std::endl; - continue; + if (Debug == true) + std::clog << "FindInCache returned end-Pointer" << std::endl; + return false; } - - if ((*Start)->Exists() == false) + + RlsVisited[RlsFile->ID] = true; + if (Debug == true) + std::clog << "with ID " << RlsFile->ID << " is valid" << std::endl; + + std::vector <pkgIndexFile *> const * const Indexes = (*i)->GetIndexFiles(); + std::copy_if(Indexes->begin(), Indexes->end(), std::back_inserter(Files), + [](pkgIndexFile const * const I) { return I->HasPackages(); }); + } + for (unsigned I = 0; I != Cache.HeaderP->ReleaseFileCount; ++I) + if (RlsVisited[I] == false) + { + if (Debug == true) + std::clog << "RlsFile with ID" << I << " wasn't visited" << std::endl; + return false; + } + + std::copy(Start, End, std::back_inserter(Files)); + + /* Now we check every index file, see if it is in the cache, + verify the IMS data and check that it is on the disk too.. */ + std::unique_ptr<bool[]> Visited(new bool[Cache.HeaderP->PackageFileCount]); + memset(Visited.get(),0,sizeof(Visited[0])*Cache.HeaderP->PackageFileCount); + for (std::vector<pkgIndexFile *>::const_reverse_iterator PkgFile = Files.rbegin(); PkgFile != Files.rend(); ++PkgFile) + { + if (Debug == true) + std::clog << "Checking PkgFile " << (*PkgFile)->Describe() << ": "; + if ((*PkgFile)->Exists() == false) { -#if 0 // mvo: we no longer give a message here (Default Sources spec) - _error->WarningE("stat",_("Couldn't stat source package list %s"), - (*Start)->Describe().c_str()); -#endif if (Debug == true) std::clog << "file doesn't exist" << std::endl; continue; } // FindInCache is also expected to do an IMS check. - pkgCache::PkgFileIterator File = (*Start)->FindInCache(Cache); + pkgCache::PkgFileIterator File = (*PkgFile)->FindInCache(Cache); if (File.end() == true) { if (Debug == true) @@ -1214,15 +1319,15 @@ static bool CheckValidity(const string &CacheFile, if (Debug == true) std::clog << "with ID " << File->ID << " is valid" << std::endl; } - + for (unsigned I = 0; I != Cache.HeaderP->PackageFileCount; I++) if (Visited[I] == false) { if (Debug == true) - std::clog << "File with ID" << I << " wasn't visited" << std::endl; + std::clog << "PkgFile with ID" << I << " wasn't visited" << std::endl; return false; } - + if (_error->PendingError() == true) { if (Debug == true) @@ -1235,7 +1340,7 @@ static bool CheckValidity(const string &CacheFile, } if (OutMap != 0) - *OutMap = Map.UnGuard(); + *OutMap = Map.release(); return true; } /*}}}*/ @@ -1243,9 +1348,20 @@ static bool CheckValidity(const string &CacheFile, // --------------------------------------------------------------------- /* Size is kind of an abstract notion that is only used for the progress meter */ -static map_filesize_t ComputeSize(FileIterator Start,FileIterator End) +static map_filesize_t ComputeSize(pkgSourceList const * const List, FileIterator Start,FileIterator End) { map_filesize_t TotalSize = 0; + if (List != NULL) + { + for (pkgSourceList::const_iterator i = List->begin(); i != List->end(); ++i) + { + std::vector <pkgIndexFile *> *Indexes = (*i)->GetIndexFiles(); + for (std::vector<pkgIndexFile *>::const_iterator j = Indexes->begin(); j != Indexes->end(); ++j) + if ((*j)->HasPackages() == true) + TotalSize += (*j)->Size(); + } + } + for (; Start < End; ++Start) { if ((*Start)->HasPackages() == false) @@ -1256,60 +1372,80 @@ static map_filesize_t ComputeSize(FileIterator Start,FileIterator End) } /*}}}*/ // BuildCache - Merge the list of index files into the cache /*{{{*/ -// --------------------------------------------------------------------- -/* */ static bool BuildCache(pkgCacheGenerator &Gen, - OpProgress *Progress, + OpProgress * const Progress, map_filesize_t &CurrentSize,map_filesize_t TotalSize, - FileIterator Start, FileIterator End) + pkgSourceList const * const List, + FileIterator const Start, FileIterator const End) { - FileIterator I; - for (I = Start; I != End; ++I) - { - if ((*I)->HasPackages() == false) - continue; - - if ((*I)->Exists() == false) - continue; + std::vector<pkgIndexFile *> Files; + bool mergeFailure = false; + + auto const indexFileMerge = [&](pkgIndexFile * const I) { + if (I->HasPackages() == false || mergeFailure) + return; - if ((*I)->FindInCache(Gen.GetCache()).end() == false) + if (I->Exists() == false) + return; + + if (I->FindInCache(Gen.GetCache()).end() == false) { _error->Warning("Duplicate sources.list entry %s", - (*I)->Describe().c_str()); - continue; + I->Describe().c_str()); + return; } - - map_filesize_t Size = (*I)->Size(); + + map_filesize_t const Size = I->Size(); if (Progress != NULL) - Progress->OverallProgress(CurrentSize,TotalSize,Size,_("Reading package lists")); + Progress->OverallProgress(CurrentSize, TotalSize, Size, _("Reading package lists")); CurrentSize += Size; - - if ((*I)->Merge(Gen,Progress) == false) - return false; - } - if (Gen.HasFileDeps() == true) + if (I->Merge(Gen,Progress) == false) + mergeFailure = true; + }; + + if (List != NULL) { - if (Progress != NULL) - Progress->Done(); - TotalSize = ComputeSize(Start, End); - CurrentSize = 0; - for (I = Start; I != End; ++I) + for (pkgSourceList::const_iterator i = List->begin(); i != List->end(); ++i) { - map_filesize_t Size = (*I)->Size(); - if (Progress != NULL) - Progress->OverallProgress(CurrentSize,TotalSize,Size,_("Collecting File Provides")); - CurrentSize += Size; - if ((*I)->MergeFileProvides(Gen,Progress) == false) + if ((*i)->FindInCache(Gen.GetCache(), false).end() == false) + { + _error->Warning("Duplicate sources.list entry %s", + (*i)->Describe().c_str()); + continue; + } + + if ((*i)->Merge(Gen, Progress) == false) + return false; + + std::vector <pkgIndexFile *> *Indexes = (*i)->GetIndexFiles(); + if (Indexes != NULL) + std::for_each(Indexes->begin(), Indexes->end(), indexFileMerge); + if (mergeFailure) return false; } } - + + if (Start != End) + { + Gen.SelectReleaseFile("", ""); + std::for_each(Start, End, indexFileMerge); + if (mergeFailure) + return false; + } return true; } /*}}}*/ -// CacheGenerator::CreateDynamicMMap - load an mmap with configuration options /*{{{*/ -DynamicMMap* pkgCacheGenerator::CreateDynamicMMap(FileFd *CacheF, unsigned long Flags) { +// CacheGenerator::MakeStatusCache - Construct the status cache /*{{{*/ +// --------------------------------------------------------------------- +/* This makes sure that the status cache (the cache that has all + index files from the sources list and all local ones) is ready + to be mmaped. If OutMap is not zero then a MMap object representing + the cache will be stored there. This is pretty much mandetory if you + are using AllowMem. AllowMem lets the function be run as non-root + where it builds the cache 'fast' into a memory buffer. */ +static DynamicMMap* CreateDynamicMMap(FileFd * const CacheF, unsigned long Flags) +{ map_filesize_t const MapStart = _config->FindI("APT::Cache-Start", 24*1024*1024); map_filesize_t const MapGrow = _config->FindI("APT::Cache-Grow", 1*1024*1024); map_filesize_t const MapLimit = _config->FindI("APT::Cache-Limit", 0); @@ -1321,15 +1457,42 @@ DynamicMMap* pkgCacheGenerator::CreateDynamicMMap(FileFd *CacheF, unsigned long else return new DynamicMMap(Flags, MapStart, MapGrow, MapLimit); } - /*}}}*/ -// CacheGenerator::MakeStatusCache - Construct the status cache /*{{{*/ -// --------------------------------------------------------------------- -/* This makes sure that the status cache (the cache that has all - index files from the sources list and all local ones) is ready - to be mmaped. If OutMap is not zero then a MMap object representing - the cache will be stored there. This is pretty much mandetory if you - are using AllowMem. AllowMem lets the function be run as non-root - where it builds the cache 'fast' into a memory buffer. */ +static bool writeBackMMapToFile(pkgCacheGenerator * const Gen, DynamicMMap * const Map, + std::string const &FileName) +{ + FileFd SCacheF(FileName, FileFd::WriteAtomic); + if (_error->PendingError() == true) + return false; + + fchmod(SCacheF.Fd(),0644); + + // Write out the main data + if (SCacheF.Write(Map->Data(),Map->Size()) == false) + return _error->Error(_("IO Error saving source cache")); + SCacheF.Sync(); + + // Write out the proper header + Gen->GetCache().HeaderP->Dirty = false; + if (SCacheF.Seek(0) == false || + SCacheF.Write(Map->Data(),sizeof(*Gen->GetCache().HeaderP)) == false) + return _error->Error(_("IO Error saving source cache")); + Gen->GetCache().HeaderP->Dirty = true; + SCacheF.Sync(); + return true; +} +static bool loadBackMMapFromFile(std::unique_ptr<pkgCacheGenerator> &Gen, + std::unique_ptr<DynamicMMap> &Map, OpProgress * const Progress, std::string const &FileName) +{ + Map.reset(CreateDynamicMMap(NULL, 0)); + FileFd CacheF(FileName, FileFd::ReadOnly); + map_pointer_t const alloc = Map->RawAllocate(CacheF.Size()); + if ((alloc == 0 && _error->PendingError()) + || CacheF.Read((unsigned char *)Map->Data() + alloc, + CacheF.Size()) == false) + return false; + Gen.reset(new pkgCacheGenerator(Map.get(),Progress)); + return true; +} APT_DEPRECATED bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress, MMap **OutMap, bool AllowMem) { return pkgCacheGenerator::MakeStatusCache(List, &Progress, OutMap, AllowMem); } @@ -1339,18 +1502,6 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress bool const Debug = _config->FindB("Debug::pkgCacheGen", false); std::vector<pkgIndexFile *> Files; - for (std::vector<metaIndex *>::const_iterator i = List.begin(); - i != List.end(); - ++i) - { - std::vector <pkgIndexFile *> *Indexes = (*i)->GetIndexFiles(); - for (std::vector<pkgIndexFile *>::const_iterator j = Indexes->begin(); - j != Indexes->end(); - ++j) - Files.push_back (*j); - } - - map_filesize_t const EndOfSource = Files.size(); if (_system->AddStatusFiles(Files) == false) return false; @@ -1371,160 +1522,130 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress CreateDirectory(dir, flNotFile(SrcCacheFile)); } - // Decide if we can write to the cache - bool Writeable = false; - if (CacheFile.empty() == false) - Writeable = access(flNotFile(CacheFile).c_str(),W_OK) == 0; - else - if (SrcCacheFile.empty() == false) - Writeable = access(flNotFile(SrcCacheFile).c_str(),W_OK) == 0; - if (Debug == true) - std::clog << "Do we have write-access to the cache files? " << (Writeable ? "YES" : "NO") << std::endl; - - if (Writeable == false && AllowMem == false && CacheFile.empty() == false) - return _error->Error(_("Unable to write to %s"),flNotFile(CacheFile).c_str()); - if (Progress != NULL) Progress->OverallProgress(0,1,1,_("Reading package lists")); - // Cache is OK, Fin. - if (CheckValidity(CacheFile, List, Files.begin(),Files.end(),OutMap) == true) + bool pkgcache_fine = false; + bool srcpkgcache_fine = false; + bool volatile_fine = List.GetVolatileFiles().empty(); + + if (CheckValidity(CacheFile, List, Files.begin(), Files.end(), volatile_fine ? OutMap : NULL) == true) { - if (Progress != NULL) - Progress->OverallProgress(1,1,1,_("Reading package lists")); if (Debug == true) - std::clog << "pkgcache.bin is valid - no need to build anything" << std::endl; - return true; + std::clog << "pkgcache.bin is valid - no need to build any cache" << std::endl; + pkgcache_fine = true; + srcpkgcache_fine = true; } - else if (Debug == true) - std::clog << "pkgcache.bin is NOT valid" << std::endl; - - /* At this point we know we need to reconstruct the package cache, - begin. */ - SPtr<FileFd> CacheF; - SPtr<DynamicMMap> Map; - if (Writeable == true && CacheFile.empty() == false) + if (pkgcache_fine == false) { - _error->PushToStack(); - unlink(CacheFile.c_str()); - CacheF = new FileFd(CacheFile,FileFd::WriteAtomic); - fchmod(CacheF->Fd(),0644); - Map = CreateDynamicMMap(CacheF, MMap::Public); - if (_error->PendingError() == true) + if (CheckValidity(SrcCacheFile, List, Files.end(), Files.end()) == true) { - delete CacheF.UnGuard(); - delete Map.UnGuard(); if (Debug == true) - std::clog << "Open filebased MMap FAILED" << std::endl; - Writeable = false; - if (AllowMem == false) - { - _error->MergeWithStack(); - return false; - } - _error->RevertToStack(); - } - else - { - _error->MergeWithStack(); - if (Debug == true) - std::clog << "Open filebased MMap" << std::endl; + std::clog << "srcpkgcache.bin is valid - it can be reused" << std::endl; + srcpkgcache_fine = true; } } - if (Writeable == false || CacheFile.empty() == true) + + if (volatile_fine == true && srcpkgcache_fine == true && pkgcache_fine == true) { - // Just build it in memory.. - Map = CreateDynamicMMap(NULL); - if (Debug == true) - std::clog << "Open memory Map (not filebased)" << std::endl; + if (Progress != NULL) + Progress->OverallProgress(1,1,1,_("Reading package lists")); + return true; } - - // Lets try the source cache. - map_filesize_t CurrentSize = 0; - map_filesize_t TotalSize = 0; - if (CheckValidity(SrcCacheFile, List, Files.begin(), - Files.begin()+EndOfSource) == true) + + bool Writeable = false; + if (srcpkgcache_fine == false || pkgcache_fine == false) { + if (CacheFile.empty() == false) + Writeable = access(flNotFile(CacheFile).c_str(),W_OK) == 0; + else if (SrcCacheFile.empty() == false) + Writeable = access(flNotFile(SrcCacheFile).c_str(),W_OK) == 0; + if (Debug == true) - std::clog << "srcpkgcache.bin is valid - populate MMap with it." << std::endl; - // Preload the map with the source cache - FileFd SCacheF(SrcCacheFile,FileFd::ReadOnly); - map_pointer_t const alloc = Map->RawAllocate(SCacheF.Size()); - if ((alloc == 0 && _error->PendingError()) - || SCacheF.Read((unsigned char *)Map->Data() + alloc, - SCacheF.Size()) == false) - return false; + std::clog << "Do we have write-access to the cache files? " << (Writeable ? "YES" : "NO") << std::endl; - TotalSize = ComputeSize(Files.begin()+EndOfSource,Files.end()); + if (Writeable == false && AllowMem == false) + { + if (CacheFile.empty() == false) + return _error->Error(_("Unable to write to %s"),flNotFile(CacheFile).c_str()); + else if (SrcCacheFile.empty() == false) + return _error->Error(_("Unable to write to %s"),flNotFile(SrcCacheFile).c_str()); + else + return _error->Error("Unable to create caches as file usage is disabled, but memory not allowed either!"); + } + } - // Build the status cache - pkgCacheGenerator Gen(Map.Get(),Progress); - if (_error->PendingError() == true) - return false; - if (BuildCache(Gen,Progress,CurrentSize,TotalSize, - Files.begin()+EndOfSource,Files.end()) == false) + // At this point we know we need to construct something, so get storage ready + std::unique_ptr<DynamicMMap> Map(CreateDynamicMMap(NULL, 0)); + if (Debug == true) + std::clog << "Open memory Map (not filebased)" << std::endl; + + std::unique_ptr<pkgCacheGenerator> Gen{nullptr}; + map_filesize_t CurrentSize = 0; + std::vector<pkgIndexFile*> VolatileFiles = List.GetVolatileFiles(); + map_filesize_t TotalSize = ComputeSize(NULL, VolatileFiles.begin(), VolatileFiles.end()); + if (srcpkgcache_fine == true && pkgcache_fine == false) + { + if (Debug == true) + std::clog << "srcpkgcache.bin was valid - populate MMap with it" << std::endl; + if (loadBackMMapFromFile(Gen, Map, Progress, SrcCacheFile) == false) return false; + srcpkgcache_fine = true; + TotalSize += ComputeSize(NULL, Files.begin(), Files.end()); } - else + else if (srcpkgcache_fine == false) { if (Debug == true) std::clog << "srcpkgcache.bin is NOT valid - rebuild" << std::endl; - TotalSize = ComputeSize(Files.begin(),Files.end()); - - // Build the source cache - pkgCacheGenerator Gen(Map.Get(),Progress); - if (_error->PendingError() == true) - return false; - if (BuildCache(Gen,Progress,CurrentSize,TotalSize, - Files.begin(),Files.begin()+EndOfSource) == false) + Gen.reset(new pkgCacheGenerator(Map.get(),Progress)); + + TotalSize += ComputeSize(&List, Files.begin(),Files.end()); + if (BuildCache(*Gen, Progress, CurrentSize, TotalSize, &List, + Files.end(),Files.end()) == false) return false; - - // Write it back + if (Writeable == true && SrcCacheFile.empty() == false) - { - FileFd SCacheF(SrcCacheFile,FileFd::WriteAtomic); - if (_error->PendingError() == true) + if (writeBackMMapToFile(Gen.get(), Map.get(), SrcCacheFile) == false) return false; - - fchmod(SCacheF.Fd(),0644); - - // Write out the main data - if (SCacheF.Write(Map->Data(),Map->Size()) == false) - return _error->Error(_("IO Error saving source cache")); - SCacheF.Sync(); - - // Write out the proper header - Gen.GetCache().HeaderP->Dirty = false; - if (SCacheF.Seek(0) == false || - SCacheF.Write(Map->Data(),sizeof(*Gen.GetCache().HeaderP)) == false) - return _error->Error(_("IO Error saving source cache")); - Gen.GetCache().HeaderP->Dirty = true; - SCacheF.Sync(); - } - - // Build the status cache - if (BuildCache(Gen,Progress,CurrentSize,TotalSize, - Files.begin()+EndOfSource,Files.end()) == false) + } + + if (pkgcache_fine == false) + { + if (Debug == true) + std::clog << "Building status cache in pkgcache.bin now" << std::endl; + if (BuildCache(*Gen, Progress, CurrentSize, TotalSize, NULL, + Files.begin(), Files.end()) == false) return false; + + if (Writeable == true && CacheFile.empty() == false) + if (writeBackMMapToFile(Gen.get(), Map.get(), CacheFile) == false) + return false; } + if (Debug == true) - std::clog << "Caches are ready for shipping" << std::endl; + std::clog << "Caches done. Now bring in the volatile files (if any)" << std::endl; - if (_error->PendingError() == true) - return false; - if (OutMap != 0) + if (volatile_fine == false) { - if (CacheF != 0) + if (Gen == nullptr) { - delete Map.UnGuard(); - *OutMap = new MMap(*CacheF,0); + if (Debug == true) + std::clog << "Populate new MMap with cachefile contents" << std::endl; + if (loadBackMMapFromFile(Gen, Map, Progress, CacheFile) == false) + return false; } - else - { - *OutMap = Map.UnGuard(); - } + + Files = List.GetVolatileFiles(); + if (BuildCache(*Gen, Progress, CurrentSize, TotalSize, NULL, + Files.begin(), Files.end()) == false) + return false; } - + + if (OutMap != nullptr) + *OutMap = Map.release(); + + if (Debug == true) + std::clog << "Everything is ready for shipping" << std::endl; return true; } /*}}}*/ @@ -1536,29 +1657,28 @@ APT_DEPRECATED bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **Ou bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **OutMap) { std::vector<pkgIndexFile *> Files; - map_filesize_t EndOfSource = Files.size(); if (_system->AddStatusFiles(Files) == false) return false; - SPtr<DynamicMMap> Map = CreateDynamicMMap(NULL); + std::unique_ptr<DynamicMMap> Map(CreateDynamicMMap(NULL, 0)); map_filesize_t CurrentSize = 0; map_filesize_t TotalSize = 0; - TotalSize = ComputeSize(Files.begin()+EndOfSource,Files.end()); + TotalSize = ComputeSize(NULL, Files.begin(), Files.end()); // Build the status cache if (Progress != NULL) Progress->OverallProgress(0,1,1,_("Reading package lists")); - pkgCacheGenerator Gen(Map.Get(),Progress); + pkgCacheGenerator Gen(Map.get(),Progress); if (_error->PendingError() == true) return false; - if (BuildCache(Gen,Progress,CurrentSize,TotalSize, - Files.begin()+EndOfSource,Files.end()) == false) + if (BuildCache(Gen,Progress,CurrentSize,TotalSize, NULL, + Files.begin(), Files.end()) == false) return false; if (_error->PendingError() == true) return false; - *OutMap = Map.UnGuard(); + *OutMap = Map.release(); return true; } @@ -1576,9 +1696,6 @@ static bool IsDuplicateDescription(pkgCache::DescIterator Desc, return false; } /*}}}*/ -// CacheGenerator::FinishCache /*{{{*/ -bool pkgCacheGenerator::FinishCache(OpProgress * /*Progress*/) -{ - return true; -} - /*}}}*/ + +pkgCacheListParser::pkgCacheListParser() : Owner(NULL), OldDepLast(NULL), d(NULL) {} +pkgCacheListParser::~pkgCacheListParser() {} diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h index c4ace713d..46fccdaa5 100644 --- a/apt-pkg/pkgcachegen.h +++ b/apt-pkg/pkgcachegen.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: pkgcachegen.h,v 1.19 2002/07/08 03:13:30 jgg Exp $ /* ###################################################################### Package Cache Generator - Generator for the cache structure. @@ -33,10 +32,10 @@ class FileFd; class pkgSourceList; class OpProgress; class pkgIndexFile; +class pkgCacheListParser; class APT_HIDDEN pkgCacheGenerator /*{{{*/ { - private: APT_HIDDEN map_stringitem_t WriteStringInMap(std::string const &String) { return WriteStringInMap(String.c_str()); }; APT_HIDDEN map_stringitem_t WriteStringInMap(const char *String); APT_HIDDEN map_stringitem_t WriteStringInMap(const char *String, const unsigned long &Len); @@ -47,15 +46,15 @@ class APT_HIDDEN pkgCacheGenerator /*{{{*/ std::map<std::string,map_stringitem_t> strPkgNames; std::map<std::string,map_stringitem_t> strVersions; + friend class pkgCacheListParser; + typedef pkgCacheListParser ListParser; + public: - - class ListParser; - friend class ListParser; template<typename Iter> class Dynamic { public: static std::vector<Iter*> toReMap; - Dynamic(Iter &I) { + explicit Dynamic(Iter &I) { toReMap.push_back(&I); } @@ -69,29 +68,27 @@ class APT_HIDDEN pkgCacheGenerator /*{{{*/ DynamicMMap ⤅ pkgCache Cache; OpProgress *Progress; - + + std::string RlsFileName; + pkgCache::ReleaseFile *CurrentRlsFile; std::string PkgFileName; pkgCache::PackageFile *CurrentFile; - // Flag file dependencies - bool FoundFileDeps; - bool NewGroup(pkgCache::GrpIterator &Grp,const std::string &Name); bool NewPackage(pkgCache::PkgIterator &Pkg,const std::string &Name, const std::string &Arch); bool NewFileVer(pkgCache::VerIterator &Ver,ListParser &List); bool NewFileDesc(pkgCache::DescIterator &Desc,ListParser &List); bool NewDepends(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver, - std::string const &Version, unsigned int const &Op, - unsigned int const &Type, map_pointer_t* &OldDepLast); - bool NewDepends(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver, - map_pointer_t const Version, unsigned int const &Op, - unsigned int const &Type, map_pointer_t* &OldDepLast); + map_pointer_t const Version, uint8_t const Op, + uint8_t const Type, map_pointer_t* &OldDepLast); map_pointer_t NewVersion(pkgCache::VerIterator &Ver,const std::string &VerStr,map_pointer_t const Next) APT_DEPRECATED { return NewVersion(Ver, VerStr, 0, 0, Next); } map_pointer_t NewVersion(pkgCache::VerIterator &Ver,const std::string &VerStr, map_pointer_t const ParentPkg, unsigned short const Hash, map_pointer_t const Next); map_pointer_t NewDescription(pkgCache::DescIterator &Desc,const std::string &Lang,const MD5SumValue &md5sum,map_stringitem_t const idxmd5str); + bool NewProvides(pkgCache::VerIterator &Ver, pkgCache::PkgIterator &Pkg, + map_stringitem_t const ProvidesVersion, uint8_t const Flags); public: @@ -100,28 +97,26 @@ class APT_HIDDEN pkgCacheGenerator /*{{{*/ inline map_stringitem_t StoreString(enum StringType const type, const std::string &S) {return StoreString(type, S.c_str(),S.length());}; void DropProgress() {Progress = 0;}; - bool SelectFile(const std::string &File,const std::string &Site,pkgIndexFile const &Index, - unsigned long Flags = 0); + bool SelectFile(const std::string &File,pkgIndexFile const &Index, std::string const &Architecture, std::string const &Component, unsigned long Flags = 0); + bool SelectReleaseFile(const std::string &File, const std::string &Site, unsigned long Flags = 0); bool MergeList(ListParser &List,pkgCache::VerIterator *Ver = 0); inline pkgCache &GetCache() {return Cache;}; - inline pkgCache::PkgFileIterator GetCurFile() + inline pkgCache::PkgFileIterator GetCurFile() {return pkgCache::PkgFileIterator(Cache,CurrentFile);}; - - bool HasFileDeps() {return FoundFileDeps;}; - bool MergeFileProvides(ListParser &List); - bool FinishCache(OpProgress *Progress) APT_DEPRECATED APT_CONST; + inline pkgCache::RlsFileIterator GetCurRlsFile() + {return pkgCache::RlsFileIterator(Cache,CurrentRlsFile);}; APT_PUBLIC static bool MakeStatusCache(pkgSourceList &List,OpProgress *Progress, MMap **OutMap = 0,bool AllowMem = false); APT_PUBLIC static bool MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **OutMap); - APT_PUBLIC static DynamicMMap* CreateDynamicMMap(FileFd *CacheF, unsigned long Flags = 0); void ReMap(void const * const oldMap, void const * const newMap); pkgCacheGenerator(DynamicMMap *Map,OpProgress *Progress); - ~pkgCacheGenerator(); + virtual ~pkgCacheGenerator(); private: + void * const d; APT_HIDDEN bool MergeListGroup(ListParser &List, std::string const &GrpName); APT_HIDDEN bool MergeListPackage(ListParser &List, pkgCache::PkgIterator &Pkg); APT_HIDDEN bool MergeListVersion(ListParser &List, pkgCache::PkgIterator &Pkg, @@ -136,18 +131,17 @@ class APT_HIDDEN pkgCacheGenerator /*{{{*/ }; /*}}}*/ // This is the abstract package list parser class. /*{{{*/ -class APT_HIDDEN pkgCacheGenerator::ListParser +class APT_HIDDEN pkgCacheListParser { pkgCacheGenerator *Owner; friend class pkgCacheGenerator; - + // Some cache items pkgCache::VerIterator OldDepVer; map_pointer_t *OldDepLast; - // Flag file dependencies - bool FoundFileDeps; - + void * const d; + protected: inline map_stringitem_t StoreString(pkgCacheGenerator::StringType const type, std::string const &S) {return Owner->StoreString(type, S);}; @@ -156,10 +150,13 @@ class APT_HIDDEN pkgCacheGenerator::ListParser inline map_stringitem_t WriteString(const std::string &S) {return Owner->WriteStringInMap(S);}; inline map_stringitem_t WriteString(const char *S,unsigned int Size) {return Owner->WriteStringInMap(S,Size);}; bool NewDepends(pkgCache::VerIterator &Ver,const std::string &Package, const std::string &Arch, - const std::string &Version,unsigned int Op, - unsigned int Type); + const std::string &Version,uint8_t const Op, + uint8_t const Type); bool NewProvides(pkgCache::VerIterator &Ver,const std::string &PkgName, - const std::string &PkgArch, const std::string &Version); + const std::string &PkgArch, const std::string &Version, + uint8_t const Flags); + bool NewProvidesAllArch(pkgCache::VerIterator &Ver, std::string const &Package, + std::string const &Version, uint8_t const Flags); public: @@ -178,10 +175,7 @@ class APT_HIDDEN pkgCacheGenerator::ListParser * \param Hash of the currently parsed version * \param Ver to compare with */ -#if APT_PKG_ABI >= 413 - virtual -#endif - APT_PURE bool SameVersion(unsigned short const Hash, pkgCache::VerIterator const &Ver); + virtual bool SameVersion(unsigned short const Hash, pkgCache::VerIterator const &Ver); virtual bool UsePackage(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver) = 0; virtual map_filesize_t Offset() = 0; @@ -189,12 +183,11 @@ class APT_HIDDEN pkgCacheGenerator::ListParser virtual bool Step() = 0; - inline bool HasFileDeps() {return FoundFileDeps;}; virtual bool CollectFileProvides(pkgCache &/*Cache*/, pkgCache::VerIterator &/*Ver*/) {return true;}; - ListParser() : Owner(NULL), OldDepLast(NULL), FoundFileDeps(false) {}; - virtual ~ListParser() {}; + pkgCacheListParser(); + virtual ~pkgCacheListParser(); }; /*}}}*/ diff --git a/apt-pkg/pkgrecords.cc b/apt-pkg/pkgrecords.cc index 859af3a09..ef4c17cd2 100644 --- a/apt-pkg/pkgrecords.cc +++ b/apt-pkg/pkgrecords.cc @@ -76,3 +76,6 @@ pkgRecords::Parser &pkgRecords::Lookup(pkgCache::DescFileIterator const &Desc) return *Files[Desc.File()->ID]; } /*}}}*/ + +pkgRecords::Parser::Parser() : d(NULL) {} +pkgRecords::Parser::~Parser() {} diff --git a/apt-pkg/pkgrecords.h b/apt-pkg/pkgrecords.h index bcc05baba..0ed731f1f 100644 --- a/apt-pkg/pkgrecords.h +++ b/apt-pkg/pkgrecords.h @@ -31,7 +31,7 @@ class pkgRecords /*{{{*/ private: /** \brief dpointer placeholder (for later in case we need it) */ - void *d; + void * const d; pkgCache &Cache; std::vector<Parser *>Files; @@ -42,8 +42,8 @@ class pkgRecords /*{{{*/ Parser &Lookup(pkgCache::DescFileIterator const &Desc); // Construct destruct - pkgRecords(pkgCache &Cache); - ~pkgRecords(); + explicit pkgRecords(pkgCache &Cache); + virtual ~pkgRecords(); }; /*}}}*/ class pkgRecords::Parser /*{{{*/ @@ -68,17 +68,10 @@ class pkgRecords::Parser /*{{{*/ * choose the hash to be used. */ virtual HashStringList Hashes() const { return HashStringList(); }; -#if APT_PKG_ABI >= 413 APT_DEPRECATED std::string MD5Hash() const { return GetHashFromHashes("MD5Sum"); }; APT_DEPRECATED std::string SHA1Hash() const { return GetHashFromHashes("SHA1"); }; APT_DEPRECATED std::string SHA256Hash() const { return GetHashFromHashes("SHA256"); }; APT_DEPRECATED std::string SHA512Hash() const { return GetHashFromHashes("SHA512"); }; -#else - APT_DEPRECATED std::string MD5Hash() { return GetHashFromHashes("MD5Sum"); }; - APT_DEPRECATED std::string SHA1Hash() { return GetHashFromHashes("SHA1"); }; - APT_DEPRECATED std::string SHA256Hash() { return GetHashFromHashes("SHA256"); }; - APT_DEPRECATED std::string SHA512Hash() { return GetHashFromHashes("SHA512"); }; -#endif // These are some general stats about the package virtual std::string Maintainer() {return std::string();}; @@ -106,10 +99,12 @@ class pkgRecords::Parser /*{{{*/ // The record in binary form virtual void GetRec(const char *&Start,const char *&Stop) {Start = Stop = 0;}; - - virtual ~Parser() {}; + + Parser(); + virtual ~Parser(); private: + void * const d; APT_HIDDEN std::string GetHashFromHashes(char const * const type) const { HashStringList const hashes = Hashes(); diff --git a/apt-pkg/pkgsystem.cc b/apt-pkg/pkgsystem.cc index 14d090c7a..a6b61e655 100644 --- a/apt-pkg/pkgsystem.cc +++ b/apt-pkg/pkgsystem.cc @@ -27,7 +27,8 @@ unsigned long pkgSystem::GlobalListLen = 0; // System::pkgSystem - Constructor /*{{{*/ // --------------------------------------------------------------------- /* Add it to the global list.. */ -pkgSystem::pkgSystem() : Label(NULL), VS(NULL) +pkgSystem::pkgSystem(char const * const label, pkgVersioningSystem * const vs) : + Label(label), VS(vs), d(NULL) { assert(GlobalListLen < sizeof(SysList)/sizeof(*SysList)); SysList[GlobalListLen] = this; @@ -45,3 +46,5 @@ APT_PURE pkgSystem *pkgSystem::GetSystem(const char *Label) return 0; } /*}}}*/ + +pkgSystem::~pkgSystem() {} diff --git a/apt-pkg/pkgsystem.h b/apt-pkg/pkgsystem.h index f88ffa7c8..5b31457e0 100644 --- a/apt-pkg/pkgsystem.h +++ b/apt-pkg/pkgsystem.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: pkgsystem.h,v 1.6 2002/11/11 06:55:50 doogie Exp $ /* ###################################################################### System - Abstraction for running on different systems. @@ -53,7 +52,7 @@ class Configuration; class pkgIndexFile; class pkgSystem -{ +{ public: // Global list of supported systems @@ -61,8 +60,8 @@ class pkgSystem static unsigned long GlobalListLen; static pkgSystem *GetSystem(const char *Label); - const char *Label; - pkgVersioningSystem *VS; + const char * const Label; + pkgVersioningSystem * const VS; /* Prevent other programs from touching shared data not covered by other locks (cache or state locks) */ @@ -82,7 +81,8 @@ class pkgSystem virtual bool ArchiveSupported(const char *Type) = 0; // Return a list of system index files.. - virtual bool AddStatusFiles(std::vector<pkgIndexFile *> &List) = 0; + virtual bool AddStatusFiles(std::vector<pkgIndexFile *> &List) = 0; + virtual bool FindIndex(pkgCache::PkgFileIterator File, pkgIndexFile *&Found) const = 0; @@ -91,9 +91,11 @@ class pkgSystem virtual signed Score(Configuration const &/*Cnf*/) { return 0; }; - - pkgSystem(); - virtual ~pkgSystem() {}; + + pkgSystem(char const * const Label, pkgVersioningSystem * const VS); + virtual ~pkgSystem(); + private: + void * const d; }; // The environment we are operating in. diff --git a/apt-pkg/policy.cc b/apt-pkg/policy.cc index 00693ce54..91ad1d5bf 100644 --- a/apt-pkg/policy.cc +++ b/apt-pkg/policy.cc @@ -22,10 +22,10 @@ #include <apt-pkg/strutl.h> #include <apt-pkg/fileutl.h> #include <apt-pkg/error.h> -#include <apt-pkg/sptr.h> #include <apt-pkg/cacheiterators.h> #include <apt-pkg/pkgcache.h> #include <apt-pkg/versionmatch.h> +#include <apt-pkg/version.h> #include <ctype.h> #include <stddef.h> @@ -44,15 +44,19 @@ using namespace std; // --------------------------------------------------------------------- /* Set the defaults for operation. The default mode with no loaded policy file matches the V0 policy engine. */ -pkgPolicy::pkgPolicy(pkgCache *Owner) : Pins(0), PFPriority(0), Cache(Owner) +pkgPolicy::pkgPolicy(pkgCache *Owner) : Pins(nullptr), VerPins(nullptr), + PFPriority(nullptr), Cache(Owner), d(NULL) { if (Owner == 0) return; PFPriority = new signed short[Owner->Head().PackageFileCount]; Pins = new Pin[Owner->Head().PackageCount]; + VerPins = new Pin[Owner->Head().VersionCount]; for (unsigned long I = 0; I != Owner->Head().PackageCount; I++) Pins[I].Type = pkgVersionMatch::None; + for (unsigned long I = 0; I != Owner->Head().VersionCount; I++) + VerPins[I].Type = pkgVersionMatch::None; // The config file has a master override. string DefRel = _config->Find("APT::Default-Release"); @@ -63,9 +67,9 @@ pkgPolicy::pkgPolicy(pkgCache *Owner) : Pins(0), PFPriority(0), Cache(Owner) pkgVersionMatch vm("", pkgVersionMatch::None); for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F != Cache->FileEnd(); ++F) { - if ((F->Archive != 0 && vm.ExpressionMatches(DefRel, F.Archive()) == true) || - (F->Codename != 0 && vm.ExpressionMatches(DefRel, F.Codename()) == true) || - (F->Version != 0 && vm.ExpressionMatches(DefRel, F.Version()) == true) || + if (vm.ExpressionMatches(DefRel, F.Archive()) || + vm.ExpressionMatches(DefRel, F.Codename()) || + vm.ExpressionMatches(DefRel, F.Version()) || (DefRel.length() > 2 && DefRel[1] == '=')) found = true; } @@ -86,17 +90,17 @@ bool pkgPolicy::InitDefaults() for (pkgCache::PkgFileIterator I = Cache->FileBegin(); I != Cache->FileEnd(); ++I) { PFPriority[I->ID] = 500; - if ((I->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource) + if (I.Flagged(pkgCache::Flag::NotSource)) PFPriority[I->ID] = 100; - else if ((I->Flags & pkgCache::Flag::ButAutomaticUpgrades) == pkgCache::Flag::ButAutomaticUpgrades) + else if (I.Flagged(pkgCache::Flag::ButAutomaticUpgrades)) PFPriority[I->ID] = 100; - else if ((I->Flags & pkgCache::Flag::NotAutomatic) == pkgCache::Flag::NotAutomatic) + else if (I.Flagged(pkgCache::Flag::NotAutomatic)) PFPriority[I->ID] = 1; } // Apply the defaults.. - SPtrArray<bool> Fixed = new bool[Cache->HeaderP->PackageFileCount]; - memset(Fixed,0,sizeof(*Fixed)*Cache->HeaderP->PackageFileCount); + std::unique_ptr<bool[]> Fixed(new bool[Cache->HeaderP->PackageFileCount]); + memset(Fixed.get(),0,sizeof(Fixed[0])*Cache->HeaderP->PackageFileCount); StatusOverride = false; for (vector<Pin>::const_iterator I = Defaults.begin(); I != Defaults.end(); ++I) { @@ -128,6 +132,10 @@ bool pkgPolicy::InitDefaults() best package is. */ pkgCache::VerIterator pkgPolicy::GetCandidateVer(pkgCache::PkgIterator const &Pkg) { + if (_config->FindI("APT::Policy", 1) >= 1) { + return GetCandidateVerNew(Pkg); + } + // Look for a package pin and evaluate it. signed Max = GetPriority(Pkg); pkgCache::VerIterator Pref = GetMatch(Pkg); @@ -170,8 +178,7 @@ pkgCache::VerIterator pkgPolicy::GetCandidateVer(pkgCache::PkgIterator const &Pk then it is not a candidate for installation, ever. This weeds out bogus entries that may be due to config-file states, or other. */ - if ((VF.File()->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource && - instVer == false) + if (VF.File().Flagged(pkgCache::Flag::NotSource) && instVer == false) continue; signed Prio = PFPriority[VF.File()->ID]; @@ -215,6 +222,36 @@ pkgCache::VerIterator pkgPolicy::GetCandidateVer(pkgCache::PkgIterator const &Pk return Pref; } + +// Policy::GetCandidateVer - Get the candidate install version /*{{{*/ +// --------------------------------------------------------------------- +/* Evaluate the package pins and the default list to deteremine what the + best package is. */ +pkgCache::VerIterator pkgPolicy::GetCandidateVerNew(pkgCache::PkgIterator const &Pkg) +{ + // TODO: Replace GetCandidateVer() + pkgCache::VerIterator cand; + pkgCache::VerIterator cur = Pkg.CurrentVer(); + int candPriority = -1; + pkgVersioningSystem *vs = Cache->VS; + + for (pkgCache::VerIterator ver = Pkg.VersionList(); ver.end() == false; ver++) { + int priority = GetPriority(ver); + + if (priority == 0 || priority <= candPriority) + continue; + + // TODO: Maybe optimize to not compare versions + if (!cur.end() && priority < 1000 + && (vs->CmpVersion(ver.VerStr(), cur.VerStr()) < 0)) + continue; + + candPriority = priority; + cand = ver; + } + + return cand; +} /*}}}*/ // Policy::CreatePin - Create an entry in the pin table.. /*{{{*/ // --------------------------------------------------------------------- @@ -282,6 +319,17 @@ void pkgPolicy::CreatePin(pkgVersionMatch::MatchType Type,string Name, P->Priority = Priority; P->Data = Data; matched = true; + + // Find matching version(s) and copy the pin into it + pkgVersionMatch Match(P->Data,P->Type); + for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() != true; Ver++) + { + if (Match.VersionMatches(Ver)) { + Pin *VP = VerPins + Ver->ID; + if (VP->Type == pkgVersionMatch::None) + *VP = *P; + } + } } } @@ -319,26 +367,35 @@ APT_PURE signed short pkgPolicy::GetPriority(pkgCache::PkgIterator const &Pkg) return Pins[Pkg->ID].Priority; return 0; } +APT_PURE signed short pkgPolicy::GetPriority(pkgCache::VerIterator const &Ver, bool ConsiderFiles) +{ + if (VerPins[Ver->ID].Type != pkgVersionMatch::None) + return VerPins[Ver->ID].Priority; + if (!ConsiderFiles) + return 0; + + int priority = std::numeric_limits<int>::min(); + for (pkgCache::VerFileIterator file = Ver.FileList(); file.end() == false; file++) + { + /* If this is the status file, and the current version is not the + version in the status file (ie it is not installed, or somesuch) + then it is not a candidate for installation, ever. This weeds + out bogus entries that may be due to config-file states, or + other. */ + if (file.File().Flagged(pkgCache::Flag::NotSource) && Ver.ParentPkg().CurrentVer() != Ver) { + // Ignore + } else if (GetPriority(file.File()) > priority) { + priority = GetPriority(file.File()); + } + } + + return priority == std::numeric_limits<int>::min() ? 0 : priority; +} APT_PURE signed short pkgPolicy::GetPriority(pkgCache::PkgFileIterator const &File) { return PFPriority[File->ID]; } /*}}}*/ -// PreferenceSection class - Overriding the default TrimRecord method /*{{{*/ -// --------------------------------------------------------------------- -/* The preference file is a user generated file so the parser should - therefore be a bit more friendly by allowing comments and new lines - all over the place rather than forcing a special format */ -class PreferenceSection : public pkgTagSection -{ - void TrimRecord(bool /*BeforeRecord*/, const char* &End) - { - for (; Stop < End && (Stop[0] == '\n' || Stop[0] == '\r' || Stop[0] == '#'); Stop++) - if (Stop[0] == '#') - Stop = (const char*) memchr(Stop,'\n',End-Stop); - } -}; - /*}}}*/ // ReadPinDir - Load the pin files from this dir into a Policy /*{{{*/ // --------------------------------------------------------------------- /* This will load each pin file in the given dir into a Policy. If the @@ -383,8 +440,8 @@ bool ReadPinFile(pkgPolicy &Plcy,string File) pkgTagFile TF(&Fd); if (_error->PendingError() == true) return false; - - PreferenceSection Tags; + + pkgUserTagSection Tags; while (TF.Step(Tags) == true) { // can happen when there are only comments in a record @@ -420,11 +477,18 @@ bool ReadPinFile(pkgPolicy &Plcy,string File) } for (; Word != End && isspace(*Word) != 0; Word++); - short int priority = Tags.FindI("Pin-Priority", 0); + int priority = Tags.FindI("Pin-Priority", 0); + if (priority < std::numeric_limits<short>::min() || + priority > std::numeric_limits<short>::max() || + _error->PendingError()) { + return _error->Error(_("%s: Value %s is outside the range of valid pin priorities (%d to %d)"), + File.c_str(), Tags.FindS("Pin-Priority").c_str(), + std::numeric_limits<short>::min(), + std::numeric_limits<short>::max()); + } if (priority == 0) { - _error->Warning(_("No priority (or zero) specified for pin")); - continue; + return _error->Error(_("No priority (or zero) specified for pin")); } istringstream s(Name); @@ -440,3 +504,5 @@ bool ReadPinFile(pkgPolicy &Plcy,string File) return true; } /*}}}*/ + +pkgPolicy::~pkgPolicy() {delete [] PFPriority; delete [] Pins; delete [] VerPins; } diff --git a/apt-pkg/policy.h b/apt-pkg/policy.h index f15d8c0a0..bb0ff7e27 100644 --- a/apt-pkg/policy.h +++ b/apt-pkg/policy.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: policy.h,v 1.4 2001/05/07 04:24:08 jgg Exp $ /* ###################################################################### Package Version Policy implementation @@ -60,10 +59,11 @@ class pkgPolicy : public pkgDepCache::Policy struct PkgPin : Pin { std::string Pkg; - PkgPin(std::string const &Pkg) : Pin(), Pkg(Pkg) {}; + explicit PkgPin(std::string const &Pkg) : Pin(), Pkg(Pkg) {}; }; Pin *Pins; + Pin *VerPins; signed short *PFPriority; std::vector<Pin> Defaults; std::vector<PkgPin> Unmatched; @@ -78,14 +78,18 @@ class pkgPolicy : public pkgDepCache::Policy pkgCache::VerIterator GetMatch(pkgCache::PkgIterator const &Pkg); // Things for the cache interface. - virtual pkgCache::VerIterator GetCandidateVer(pkgCache::PkgIterator const &Pkg); - virtual signed short GetPriority(pkgCache::PkgIterator const &Pkg); - virtual signed short GetPriority(pkgCache::PkgFileIterator const &File); + virtual pkgCache::VerIterator GetCandidateVer(pkgCache::PkgIterator const &Pkg) APT_OVERRIDE; + virtual signed short GetPriority(pkgCache::PkgIterator const &Pkg) APT_OVERRIDE; + virtual signed short GetPriority(pkgCache::VerIterator const &Ver, bool ConsiderFiles = true) APT_OVERRIDE; + virtual signed short GetPriority(pkgCache::PkgFileIterator const &File) APT_OVERRIDE; bool InitDefaults(); - pkgPolicy(pkgCache *Owner); - virtual ~pkgPolicy() {delete [] PFPriority; delete [] Pins;}; + explicit pkgPolicy(pkgCache *Owner); + virtual ~pkgPolicy(); + private: + APT_HIDDEN pkgCache::VerIterator GetCandidateVerNew(pkgCache::PkgIterator const &Pkg); + void * const d; }; bool ReadPinFile(pkgPolicy &Plcy, std::string File = ""); diff --git a/apt-pkg/sourcelist.cc b/apt-pkg/sourcelist.cc index 8b960572b..3e714667c 100644 --- a/apt-pkg/sourcelist.cc +++ b/apt-pkg/sourcelist.cc @@ -37,25 +37,26 @@ using namespace std; // Global list of Items supported -static pkgSourceList::Type *ItmList[10]; +static pkgSourceList::Type *ItmList[10]; pkgSourceList::Type **pkgSourceList::Type::GlobalList = ItmList; unsigned long pkgSourceList::Type::GlobalListLen = 0; // Type::Type - Constructor /*{{{*/ // --------------------------------------------------------------------- /* Link this to the global list of items*/ -pkgSourceList::Type::Type() : Name(NULL), Label(NULL) +pkgSourceList::Type::Type(char const * const pName, char const * const pLabel) : Name(pName), Label(pLabel) { ItmList[GlobalListLen] = this; - GlobalListLen++; + ++GlobalListLen; } +pkgSourceList::Type::~Type() {} /*}}}*/ // Type::GetType - Get a specific meta for a given type /*{{{*/ // --------------------------------------------------------------------- /* */ pkgSourceList::Type *pkgSourceList::Type::GetType(const char *Type) { - for (unsigned I = 0; I != GlobalListLen; I++) + for (unsigned I = 0; I != GlobalListLen; ++I) if (strcmp(GlobalList[I]->Name,Type) == 0) return GlobalList[I]; return 0; @@ -81,76 +82,102 @@ bool pkgSourceList::Type::FixupURI(string &URI) const return true; } /*}}}*/ -bool pkgSourceList::Type::ParseStanza(vector<metaIndex *> &List, +bool pkgSourceList::Type::ParseStanza(vector<metaIndex *> &List, /*{{{*/ pkgTagSection &Tags, - int i, + unsigned int const i, FileFd &Fd) { map<string, string> Options; string Enabled = Tags.FindS("Enabled"); - if (Enabled.size() > 0 && StringToBool(Enabled) == false) + if (Enabled.empty() == false && StringToBool(Enabled) == false) return true; - - // Define external/internal options - const char* option_deb822[] = { - "Architectures", "Architectures-Add", "Architectures-Remove", "Trusted", - }; - const char* option_internal[] = { - "arch", "arch+", "arch-", "trusted", - }; - for (unsigned int j=0; j < sizeof(option_deb822)/sizeof(char*); j++) - if (Tags.Exists(option_deb822[j])) + + std::map<char const * const, std::pair<char const * const, bool> > mapping; +#define APT_PLUSMINUS(X, Y) \ + mapping.insert(std::make_pair(X, std::make_pair(Y, true))); \ + mapping.insert(std::make_pair(X "Add", std::make_pair(Y "+", true))); \ + mapping.insert(std::make_pair(X "Remove", std::make_pair(Y "-", true))) + APT_PLUSMINUS("Architectures", "arch"); + APT_PLUSMINUS("Languages", "lang"); + APT_PLUSMINUS("Targets", "target"); +#undef APT_PLUSMINUS + mapping.insert(std::make_pair("Trusted", std::make_pair("trusted", false))); + mapping.insert(std::make_pair("Check-Valid-Until", std::make_pair("check-valid-until", false))); + mapping.insert(std::make_pair("Valid-Until-Min", std::make_pair("valid-until-min", false))); + mapping.insert(std::make_pair("Valid-Until-Max", std::make_pair("valid-until-max", false))); + mapping.insert(std::make_pair("Signed-By", std::make_pair("signed-by", false))); + + for (std::map<char const * const, std::pair<char const * const, bool> >::const_iterator m = mapping.begin(); m != mapping.end(); ++m) + if (Tags.Exists(m->first)) { - // for deb822 the " " is the delimiter, but the backend expects "," - std::string option = Tags.FindS(option_deb822[j]); - std::replace(option.begin(), option.end(), ' ', ','); - Options[option_internal[j]] = option; + std::string option = Tags.FindS(m->first); + // for deb822 the " " is the delimiter, but the backend expects "," + if (m->second.second == true) + std::replace(option.begin(), option.end(), ' ', ','); + Options[m->second.first] = option; } - + // now create one item per suite/section string Suite = Tags.FindS("Suites"); Suite = SubstVar(Suite,"$(ARCH)",_config->Find("APT::Architecture")); - string const Section = Tags.FindS("Sections"); - string URIS = Tags.FindS("URIs"); + string const Component = Tags.FindS("Components"); + string const URIS = Tags.FindS("URIs"); + + std::vector<std::string> const list_uris = VectorizeString(URIS, ' '); + std::vector<std::string> const list_suite = VectorizeString(Suite, ' '); + std::vector<std::string> const list_comp = VectorizeString(Component, ' '); + + if (list_uris.empty()) + // TRANSLATOR: %u is a line number, the first %s is a filename of a file with the extension "second %s" and the third %s is a unique identifier for bugreports + return _error->Error(_("Malformed entry %u in %s file %s (%s)"), i, "sources", Fd.Name().c_str(), "URI"); - std::vector<std::string> list_uris = StringSplit(URIS, " "); - std::vector<std::string> list_dist = StringSplit(Suite, " "); - std::vector<std::string> list_section = StringSplit(Section, " "); - for (std::vector<std::string>::const_iterator U = list_uris.begin(); U != list_uris.end(); ++U) { - std::string URI = (*U); - if (!FixupURI(URI)) - { - _error->Error(_("Malformed stanza %u in source list %s (URI parse)"),i,Fd.Name().c_str()); - return false; - } + std::string URI = *U; + if (U->empty() || FixupURI(URI) == false) + return _error->Error(_("Malformed entry %u in %s file %s (%s)"), i, "sources", Fd.Name().c_str(), "URI parse"); + + if (list_suite.empty()) + return _error->Error(_("Malformed entry %u in %s file %s (%s)"), i, "sources", Fd.Name().c_str(), "Suite"); - for (std::vector<std::string>::const_iterator I = list_dist.begin(); - I != list_dist.end(); ++I) + for (std::vector<std::string>::const_iterator S = list_suite.begin(); + S != list_suite.end(); ++S) { - for (std::vector<std::string>::const_iterator J = list_section.begin(); - J != list_section.end(); ++J) - { - if (CreateItem(List, URI, (*I), (*J), Options) == false) - { - return false; - } - } + if (S->empty() == false && (*S)[S->size() - 1] == '/') + { + if (list_comp.empty() == false) + return _error->Error(_("Malformed entry %u in %s file %s (%s)"), i, "sources", Fd.Name().c_str(), "absolute Suite Component"); + if (CreateItem(List, URI, *S, "", Options) == false) + return false; + } + else + { + if (list_comp.empty()) + return _error->Error(_("Malformed entry %u in %s file %s (%s)"), i, "sources", Fd.Name().c_str(), "Component"); + + for (std::vector<std::string>::const_iterator C = list_comp.begin(); + C != list_comp.end(); ++C) + { + if (CreateItem(List, URI, *S, *C, Options) == false) + { + return false; + } + } + } } } return true; } - + /*}}}*/ // Type::ParseLine - Parse a single line /*{{{*/ // --------------------------------------------------------------------- /* This is a generic one that is the 'usual' format for sources.list Weird types may override this. */ bool pkgSourceList::Type::ParseLine(vector<metaIndex *> &List, const char *Buffer, - unsigned long const &CurLine, + unsigned int const CurLine, string const &File) const { for (;Buffer != 0 && isspace(*Buffer); ++Buffer); // Skip whitespaces @@ -167,10 +194,10 @@ bool pkgSourceList::Type::ParseLine(vector<metaIndex *> &List, // get one option, e.g. option1=value1 string option; if (ParseQuoteWord(Buffer,option) == false) - return _error->Error(_("Malformed line %lu in source list %s ([option] unparseable)"),CurLine,File.c_str()); + return _error->Error(_("Malformed entry %u in %s file %s (%s)"), CurLine, "list", File.c_str(), "[option] unparseable"); if (option.length() < 3) - return _error->Error(_("Malformed line %lu in source list %s ([option] too short)"),CurLine,File.c_str()); + return _error->Error(_("Malformed entry %u in %s file %s (%s)"), CurLine, "list", File.c_str(), "[option] too short"); // accept options even if the last has no space before the ]-end marker if (option.at(option.length()-1) == ']') @@ -181,16 +208,16 @@ bool pkgSourceList::Type::ParseLine(vector<metaIndex *> &List, size_t const needle = option.find('='); if (needle == string::npos) - return _error->Error(_("Malformed line %lu in source list %s ([%s] is not an assignment)"),CurLine,File.c_str(), option.c_str()); + return _error->Error(_("Malformed entry %u in %s file %s (%s)"), CurLine, "list", File.c_str(), "[option] not assignment"); string const key = string(option, 0, needle); string const value = string(option, needle + 1, option.length()); if (key.empty() == true) - return _error->Error(_("Malformed line %lu in source list %s ([%s] has no key)"),CurLine,File.c_str(), option.c_str()); + return _error->Error(_("Malformed entry %u in %s file %s (%s)"), CurLine, "list", File.c_str(), "[option] no key"); if (value.empty() == true) - return _error->Error(_("Malformed line %lu in source list %s ([%s] key %s has no value)"),CurLine,File.c_str(),option.c_str(),key.c_str()); + return _error->Error(_("Malformed entry %u in %s file %s (%s)"), CurLine, "list", File.c_str(), "[option] no value"); Options[key] = value; } @@ -203,47 +230,42 @@ bool pkgSourceList::Type::ParseLine(vector<metaIndex *> &List, string Section; if (ParseQuoteWord(Buffer,URI) == false) - return _error->Error(_("Malformed line %lu in source list %s (URI)"),CurLine,File.c_str()); + return _error->Error(_("Malformed entry %u in %s file %s (%s)"), CurLine, "list", File.c_str(), "URI"); if (ParseQuoteWord(Buffer,Dist) == false) - return _error->Error(_("Malformed line %lu in source list %s (dist)"),CurLine,File.c_str()); - + return _error->Error(_("Malformed entry %u in %s file %s (%s)"), CurLine, "list", File.c_str(), "Suite"); + if (FixupURI(URI) == false) - return _error->Error(_("Malformed line %lu in source list %s (URI parse)"),CurLine,File.c_str()); - + return _error->Error(_("Malformed entry %u in %s file %s (%s)"), CurLine, "list", File.c_str(), "URI parse"); + // Check for an absolute dists specification. if (Dist.empty() == false && Dist[Dist.size() - 1] == '/') { if (ParseQuoteWord(Buffer,Section) == true) - return _error->Error(_("Malformed line %lu in source list %s (absolute dist)"),CurLine,File.c_str()); + return _error->Error(_("Malformed entry %u in %s file %s (%s)"), CurLine, "list", File.c_str(), "absolute Suite Component"); Dist = SubstVar(Dist,"$(ARCH)",_config->Find("APT::Architecture")); return CreateItem(List, URI, Dist, Section, Options); } - + // Grab the rest of the dists if (ParseQuoteWord(Buffer,Section) == false) - return _error->Error(_("Malformed line %lu in source list %s (dist parse)"),CurLine,File.c_str()); - + return _error->Error(_("Malformed entry %u in %s file %s (%s)"), CurLine, "list", File.c_str(), "Component"); + do { if (CreateItem(List, URI, Dist, Section, Options) == false) return false; } while (ParseQuoteWord(Buffer,Section) == true); - + return true; } /*}}}*/ // SourceList::pkgSourceList - Constructors /*{{{*/ // --------------------------------------------------------------------- /* */ -pkgSourceList::pkgSourceList() +pkgSourceList::pkgSourceList() : d(NULL) { } - -pkgSourceList::pkgSourceList(string File) -{ - Read(File); -} /*}}}*/ // SourceList::~pkgSourceList - Destructor /*{{{*/ // --------------------------------------------------------------------- @@ -252,6 +274,10 @@ pkgSourceList::~pkgSourceList() { for (const_iterator I = SrcList.begin(); I != SrcList.end(); ++I) delete *I; + SrcList.clear(); + for (auto F = VolatileFiles.begin(); F != VolatileFiles.end(); ++F) + delete (*F); + VolatileFiles.clear(); } /*}}}*/ // SourceList::ReadMainList - Read the main source list from etc /*{{{*/ @@ -301,7 +327,7 @@ void pkgSourceList::Reset() // SourceList::Read - Parse the sourcelist file /*{{{*/ // --------------------------------------------------------------------- /* */ -bool pkgSourceList::Read(string File) +bool pkgSourceList::Read(string const &File) { Reset(); return ReadAppend(File); @@ -310,71 +336,63 @@ bool pkgSourceList::Read(string File) // SourceList::ReadAppend - Parse a sourcelist file /*{{{*/ // --------------------------------------------------------------------- /* */ -bool pkgSourceList::ReadAppend(string File) +bool pkgSourceList::ReadAppend(string const &File) { - if (_config->FindB("APT::Sources::Use-Deb822", false) == true) - { - int lines_parsed =ParseFileDeb822(File); - if (lines_parsed < 0) - return false; - else if (lines_parsed > 0) - return true; - // no lines parsed ... fall through and use old style parser - } - return ParseFileOldStyle(File); + if (flExtension(File) == "sources") + return ParseFileDeb822(File); + else + return ParseFileOldStyle(File); } - + /*}}}*/ // SourceList::ReadFileOldStyle - Read Traditional style sources.list /*{{{*/ // --------------------------------------------------------------------- /* */ -bool pkgSourceList::ParseFileOldStyle(string File) +bool pkgSourceList::ParseFileOldStyle(std::string const &File) { // Open the stream for reading ifstream F(File.c_str(),ios::in /*| ios::nocreate*/); if (F.fail() == true) return _error->Errno("ifstream::ifstream",_("Opening %s"),File.c_str()); - // CNC:2003-12-10 - 300 is too short. - char Buffer[1024]; - - int CurLine = 0; - while (F.eof() == false) + std::string Buffer; + for (unsigned int CurLine = 1; std::getline(F, Buffer); ++CurLine) { - F.getline(Buffer,sizeof(Buffer)); - CurLine++; - _strtabexpand(Buffer,sizeof(Buffer)); - if (F.fail() && !F.eof()) - return _error->Error(_("Line %u too long in source list %s."), - CurLine,File.c_str()); - - - char *I; - // CNC:2003-02-20 - Do not break if '#' is inside []. - for (I = Buffer; *I != 0 && *I != '#'; I++) - if (*I == '[') - { - char *b_end = strchr(I + 1, ']'); - if (b_end != NULL) - I = b_end; - } - *I = 0; - - const char *C = _strstrip(Buffer); - - // Comment or blank - if (C[0] == '#' || C[0] == 0) + // remove comments + size_t curpos = 0; + while ((curpos = Buffer.find('#', curpos)) != std::string::npos) + { + size_t const openbrackets = std::count(Buffer.begin(), Buffer.begin() + curpos, '['); + size_t const closedbrackets = std::count(Buffer.begin(), Buffer.begin() + curpos, ']'); + if (openbrackets > closedbrackets) + { + // a # in an option, unlikely, but oh well, it was supported so stick to it + ++curpos; + continue; + } + Buffer.erase(curpos); + break; + } + // remove spaces before/after + curpos = Buffer.find_first_not_of(" \t\r"); + if (curpos != 0) + Buffer.erase(0, curpos); + curpos = Buffer.find_last_not_of(" \t\r"); + if (curpos != std::string::npos) + Buffer.erase(curpos + 1); + + if (Buffer.empty()) continue; - + // Grok it - string LineType; - if (ParseQuoteWord(C,LineType) == false) + std::string const LineType = Buffer.substr(0, Buffer.find(' ')); + if (LineType.empty() || LineType == Buffer) return _error->Error(_("Malformed line %u in source list %s (type)"),CurLine,File.c_str()); Type *Parse = Type::GetType(LineType.c_str()); if (Parse == 0) return _error->Error(_("Type '%s' is not known on line %u in source list %s"),LineType.c_str(),CurLine,File.c_str()); - - if (Parse->ParseLine(SrcList, C, CurLine, File) == false) + + if (Parse->ParseLine(SrcList, Buffer.c_str() + LineType.length(), CurLine, File) == false) return false; } return true; @@ -383,30 +401,25 @@ bool pkgSourceList::ParseFileOldStyle(string File) // SourceList::ParseFileDeb822 - Parse deb822 style sources.list /*{{{*/ // --------------------------------------------------------------------- /* Returns: the number of stanzas parsed*/ -int pkgSourceList::ParseFileDeb822(string File) +bool pkgSourceList::ParseFileDeb822(string const &File) { - pkgTagSection Tags; - unsigned int i=0; + pkgUserTagSection Tags; + unsigned int i = 1; // see if we can read the file - _error->PushToStack(); FileFd Fd(File, FileFd::ReadOnly); pkgTagFile Sources(&Fd); if (_error->PendingError() == true) - { - _error->RevertToStack(); - return 0; - } - _error->MergeWithStack(); - + return _error->Error(_("Malformed stanza %u in source list %s (type)"),i,File.c_str()); + // read step by step while (Sources.Step(Tags) == true) { - if(!Tags.Exists("Types")) - continue; + if(Tags.Exists("Types") == false) + return _error->Error(_("Malformed stanza %u in source list %s (type)"),i,File.c_str()); string const types = Tags.FindS("Types"); - std::vector<std::string> list_types = StringSplit(types, " "); + std::vector<std::string> const list_types = VectorizeString(types, ' '); for (std::vector<std::string>::const_iterator I = list_types.begin(); I != list_types.end(); ++I) { @@ -414,18 +427,16 @@ int pkgSourceList::ParseFileDeb822(string File) if (Parse == 0) { _error->Error(_("Type '%s' is not known on stanza %u in source list %s"), (*I).c_str(),i,Fd.Name().c_str()); - return -1; + return false; } - + if (!Parse->ParseStanza(SrcList, Tags, i, Fd)) - return -1; + return false; - i++; + ++i; } } - - // we are done, return the number of stanzas read - return i; + return true; } /*}}}*/ // SourceList::FindIndex - Get the index associated with a file /*{{{*/ @@ -447,7 +458,15 @@ bool pkgSourceList::FindIndex(pkgCache::PkgFileIterator File, } } } - + for (vector<pkgIndexFile *>::const_iterator J = VolatileFiles.begin(); + J != VolatileFiles.end(); ++J) + { + if ((*J)->FindInCache(*File.Cache()) == File) + { + Found = (*J); + return true; + } + } return false; } /*}}}*/ @@ -467,9 +486,12 @@ bool pkgSourceList::GetIndexes(pkgAcquire *Owner, bool GetAll) const // Based on ReadConfigDir() /*{{{*/ // --------------------------------------------------------------------- /* */ -bool pkgSourceList::ReadSourceDir(string Dir) +bool pkgSourceList::ReadSourceDir(string const &Dir) { - vector<string> const List = GetListOfFilesInDir(Dir, "list", true); + std::vector<std::string> ext; + ext.push_back("list"); + ext.push_back("sources"); + std::vector<std::string> const List = GetListOfFilesInDir(Dir, ext, true); // Read the files for (vector<string>::const_iterator I = List.begin(); I != List.end(); ++I) @@ -501,4 +523,14 @@ time_t pkgSourceList::GetLastModifiedTime() return mtime_sources; } /*}}}*/ - +std::vector<pkgIndexFile*> pkgSourceList::GetVolatileFiles() const /*{{{*/ +{ + return VolatileFiles; +} + /*}}}*/ +void pkgSourceList::AddVolatileFile(pkgIndexFile * const File) /*{{{*/ +{ + if (File != NULL) + VolatileFiles.push_back(File); +} + /*}}}*/ diff --git a/apt-pkg/sourcelist.h b/apt-pkg/sourcelist.h index 998357509..47a562d18 100644 --- a/apt-pkg/sourcelist.h +++ b/apt-pkg/sourcelist.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: sourcelist.h,v 1.12.2.1 2003/12/24 23:09:17 mdz Exp $ /* ###################################################################### SourceList - Manage a list of sources @@ -18,10 +17,6 @@ list all you have is a list of package index files that have the ability to be Acquired. - The vendor machanism is similar, except the vendor types are hard - wired. Before loading the source list the vendor list is loaded. - This doesn't load key data, just the checks to perform. - ##################################################################### */ /*}}}*/ #ifndef PKGLIB_SOURCELIST_H @@ -54,6 +49,8 @@ class metaIndex; class pkgSourceList { + void * const d; + std::vector<pkgIndexFile*> VolatileFiles; public: // List of supported source list types @@ -66,22 +63,22 @@ class pkgSourceList static unsigned long GlobalListLen; static Type *GetType(const char *Type) APT_PURE; - const char *Name; - const char *Label; + char const * const Name; + char const * const Label; bool FixupURI(std::string &URI) const; virtual bool ParseStanza(std::vector<metaIndex *> &List, pkgTagSection &Tags, - int stanza_n, + unsigned int const stanza_n, FileFd &Fd); virtual bool ParseLine(std::vector<metaIndex *> &List, const char *Buffer, - unsigned long const &CurLine,std::string const &File) const; + unsigned int const CurLine,std::string const &File) const; virtual bool CreateItem(std::vector<metaIndex *> &List,std::string const &URI, std::string const &Dist,std::string const &Section, std::map<std::string, std::string> const &Options) const = 0; - Type(); - virtual ~Type() {}; + Type(char const * const Name, char const * const Label); + virtual ~Type(); }; typedef std::vector<metaIndex *>::const_iterator const_iterator; @@ -90,18 +87,19 @@ class pkgSourceList std::vector<metaIndex *> SrcList; - int ParseFileDeb822(std::string File); - bool ParseFileOldStyle(std::string File); + private: + APT_HIDDEN bool ParseFileDeb822(std::string const &File); + APT_HIDDEN bool ParseFileOldStyle(std::string const &File); public: bool ReadMainList(); - bool Read(std::string File); + bool Read(std::string const &File); // CNC:2003-03-03 void Reset(); - bool ReadAppend(std::string File); - bool ReadSourceDir(std::string Dir); + bool ReadAppend(std::string const &File); + bool ReadSourceDir(std::string const &Dir); // List accessors inline const_iterator begin() const {return SrcList.begin();}; @@ -116,9 +114,26 @@ class pkgSourceList // query last-modified time time_t GetLastModifiedTime(); + /** \brief add file for parsing, but not to the cache + * + * pkgIndexFiles origining from pkgSourcesList are included in + * srcpkgcache, the status files added via #AddStatusFiles are + * included in pkgcache, but these files here are not included in + * any cache to have the possibility of having a file included just + * for a single run like a local .deb/.dsc file. + * + * The volatile files do not count as "normal" sourceslist entries, + * can't be iterated over with #begin and #end and can't be + * downloaded, but they can be found via #FindIndex. + * + * @param File is an index file; pointer-ownership is transferred + */ + void AddVolatileFile(pkgIndexFile * const File); + /** @return list of files registered with #AddVolatileFile */ + std::vector<pkgIndexFile*> GetVolatileFiles() const; + pkgSourceList(); - pkgSourceList(std::string File); - ~pkgSourceList(); + virtual ~pkgSourceList(); }; #endif diff --git a/apt-pkg/srcrecords.cc b/apt-pkg/srcrecords.cc index 3175ee75f..942f11569 100644 --- a/apt-pkg/srcrecords.cc +++ b/apt-pkg/srcrecords.cc @@ -31,7 +31,7 @@ // SrcRecords::pkgSrcRecords - Constructor /*{{{*/ // --------------------------------------------------------------------- /* Open all the source index files */ -pkgSrcRecords::pkgSrcRecords(pkgSourceList &List) : d(NULL), Files(0), Current(0) +pkgSrcRecords::pkgSrcRecords(pkgSourceList &List) : d(NULL), Files(0) { for (pkgSourceList::const_iterator I = List.begin(); I != List.end(); ++I) { @@ -178,3 +178,7 @@ bool pkgSrcRecords::Parser::Files2(std::vector<pkgSrcRecords::File2> &F2)/*{{{*/ return true; } /*}}}*/ + + +pkgSrcRecords::Parser::Parser(const pkgIndexFile *Index) : d(NULL), iIndex(Index) {} +pkgSrcRecords::Parser::~Parser() {} diff --git a/apt-pkg/srcrecords.h b/apt-pkg/srcrecords.h index c931e17b7..f0a3c463a 100644 --- a/apt-pkg/srcrecords.h +++ b/apt-pkg/srcrecords.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: srcrecords.h,v 1.8.2.1 2003/12/26 16:27:34 mdz Exp $ /* ###################################################################### Source Package Records - Allows access to source package records @@ -49,6 +48,7 @@ APT_IGNORE_DEPRECATED_POP // Abstract parser for each source record class Parser { + void * const d; protected: const pkgIndexFile *iIndex; @@ -86,14 +86,14 @@ APT_IGNORE_DEPRECATED_POP virtual bool Files(std::vector<pkgSrcRecords::File> &F) = 0; bool Files2(std::vector<pkgSrcRecords::File2> &F); - - Parser(const pkgIndexFile *Index) : iIndex(Index) {}; - virtual ~Parser() {}; + + explicit Parser(const pkgIndexFile *Index); + virtual ~Parser(); }; private: /** \brief dpointer placeholder (for later in case we need it) */ - void *d; + void * const d; // The list of files and the current parser pointer std::vector<Parser*> Files; @@ -111,8 +111,8 @@ APT_IGNORE_DEPRECATED_POP // Locate a package by name and return pointer to the Parser. // The pointer is owned by libapt. Parser* Find(const char *Package,bool const &SrcOnly = false); - - pkgSrcRecords(pkgSourceList &List); + + explicit pkgSrcRecords(pkgSourceList &List); virtual ~pkgSrcRecords(); }; diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc index 5ff495fbd..8acecd735 100644 --- a/apt-pkg/tagfile.cc +++ b/apt-pkg/tagfile.cc @@ -32,19 +32,36 @@ using std::string; class pkgTagFilePrivate { public: - pkgTagFilePrivate(FileFd *pFd, unsigned long long Size) : Fd(*pFd), Buffer(NULL), - Start(NULL), End(NULL), - Done(false), iOffset(0), - Size(Size) + void Reset(FileFd * const pFd, unsigned long long const pSize) { + if (Buffer != NULL) + free(Buffer); + Buffer = NULL; + Fd = pFd; + Start = NULL; + End = NULL; + Done = false; + iOffset = 0; + Size = pSize; } - FileFd &Fd; + + pkgTagFilePrivate(FileFd * const pFd, unsigned long long const Size) : Buffer(NULL) + { + Reset(pFd, Size); + } + FileFd * Fd; char *Buffer; char *Start; char *End; bool Done; unsigned long long iOffset; unsigned long long Size; + + ~pkgTagFilePrivate() + { + if (Buffer != NULL) + free(Buffer); + } }; class pkgTagSectionPrivate @@ -59,7 +76,7 @@ public: unsigned int StartValue; unsigned int NextInBucket; - TagData(unsigned int const StartTag) : StartTag(StartTag), EndTag(0), StartValue(0), NextInBucket(0) {} + explicit TagData(unsigned int const StartTag) : StartTag(StartTag), EndTag(0), StartValue(0), NextInBucket(0) {} }; std::vector<TagData> Tags; }; @@ -83,27 +100,21 @@ static unsigned long AlphaHash(const char *Text, size_t Length) /*{{{*/ // TagFile::pkgTagFile - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ -pkgTagFile::pkgTagFile(FileFd *pFd,unsigned long long Size) - : d(NULL) +pkgTagFile::pkgTagFile(FileFd * const pFd,unsigned long long const Size) + : d(new pkgTagFilePrivate(pFd, Size + 4)) { Init(pFd, Size); } - -void pkgTagFile::Init(FileFd *pFd,unsigned long long Size) +void pkgTagFile::Init(FileFd * const pFd,unsigned long long Size) { /* The size is increased by 4 because if we start with the Size of the filename we need to try to read 1 char more to see an EOF faster, 1 char the end-pointer can be on and maybe 2 newlines need to be added to the end of the file -> 4 extra chars */ Size += 4; - if(d != NULL) - { - free(d->Buffer); - delete d; - } - d = new pkgTagFilePrivate(pFd, Size); + d->Reset(pFd, Size); - if (d->Fd.IsOpen() == false) + if (d->Fd->IsOpen() == false) d->Start = d->End = d->Buffer = 0; else d->Buffer = (char*)malloc(sizeof(char) * Size); @@ -124,7 +135,6 @@ void pkgTagFile::Init(FileFd *pFd,unsigned long long Size) /* */ pkgTagFile::~pkgTagFile() { - free(d->Buffer); delete d; } /*}}}*/ @@ -184,7 +194,7 @@ bool pkgTagFile::Step(pkgTagSection &Tag) if (Resize() == false) return _error->Error(_("Unable to parse package file %s (%d)"), - d->Fd.Name().c_str(), 1); + d->Fd->Name().c_str(), 1); } while (Tag.Scan(d->Start,d->End - d->Start, false) == false); } @@ -213,7 +223,7 @@ bool pkgTagFile::Fill() { // See if only a bit of the file is left unsigned long long const dataSize = d->Size - ((d->End - d->Buffer) + 1); - if (d->Fd.Read(d->End, dataSize, &Actual) == false) + if (d->Fd->Read(d->End, dataSize, &Actual) == false) return false; if (Actual != dataSize) d->Done = true; @@ -268,7 +278,7 @@ bool pkgTagFile::Jump(pkgTagSection &Tag,unsigned long long Offset) // Reposition and reload.. d->iOffset = Offset; d->Done = false; - if (d->Fd.Seek(Offset) == false) + if (d->Fd->Seek(Offset) == false) return false; d->End = d->Start = d->Buffer; @@ -283,7 +293,7 @@ bool pkgTagFile::Jump(pkgTagSection &Tag,unsigned long long Offset) return false; if (Tag.Scan(d->Start, d->End - d->Start, false) == false) - return _error->Error(_("Unable to parse package file %s (%d)"),d->Fd.Name().c_str(), 2); + return _error->Error(_("Unable to parse package file %s (%d)"),d->Fd->Name().c_str(), 2); return true; } @@ -293,24 +303,13 @@ bool pkgTagFile::Jump(pkgTagSection &Tag,unsigned long long Offset) /* */ APT_IGNORE_DEPRECATED_PUSH pkgTagSection::pkgTagSection() - : Section(0), d(NULL), Stop(0) + : Section(0), d(new pkgTagSectionPrivate()), Stop(0) { - d = new pkgTagSectionPrivate(); -#if APT_PKG_ABI < 413 - TagCount = 0; - memset(&Indexes, 0, sizeof(Indexes)); -#endif memset(&AlphaIndexes, 0, sizeof(AlphaIndexes)); } APT_IGNORE_DEPRECATED_POP /*}}}*/ // TagSection::Scan - Scan for the end of the header information /*{{{*/ -#if APT_PKG_ABI < 413 -bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength) -{ - return Scan(Start, MaxLength, true); -} -#endif bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const Restart) { Section = Start; @@ -336,11 +335,7 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const R } d->Tags.reserve(0x100); } -#if APT_PKG_ABI >= 413 unsigned int TagCount = d->Tags.size(); -#else - APT_IGNORE_DEPRECATED(TagCount = d->Tags.size();) -#endif if (Stop == 0) return false; @@ -367,10 +362,6 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const R lastTagData.NextInBucket = AlphaIndexes[lastTagHash]; APT_IGNORE_DEPRECATED_PUSH AlphaIndexes[lastTagHash] = TagCount; -#if APT_PKG_ABI < 413 - if (d->Tags.size() < sizeof(Indexes)/sizeof(Indexes[0])) - Indexes[d->Tags.size()] = lastTagData.StartTag; -#endif APT_IGNORE_DEPRECATED_POP d->Tags.push_back(lastTagData); } @@ -414,16 +405,10 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const R if (AlphaIndexes[lastTagHash] != 0) lastTagData.NextInBucket = AlphaIndexes[lastTagHash]; APT_IGNORE_DEPRECATED(AlphaIndexes[lastTagHash] = TagCount;) -#if APT_PKG_ABI < 413 - APT_IGNORE_DEPRECATED(Indexes[d->Tags.size()] = lastTagData.StartTag;) -#endif d->Tags.push_back(lastTagData); } pkgTagSectionPrivate::TagData const td(Stop - Section); -#if APT_PKG_ABI < 413 - APT_IGNORE_DEPRECATED(Indexes[d->Tags.size()] = td.StartTag;) -#endif d->Tags.push_back(td); TrimRecord(false,End); return true; @@ -454,11 +439,7 @@ void pkgTagSection::Trim() } /*}}}*/ // TagSection::Exists - return True if a tag exists /*{{{*/ -#if APT_PKG_ABI >= 413 bool pkgTagSection::Exists(const char* const Tag) const -#else -bool pkgTagSection::Exists(const char* const Tag) -#endif { unsigned int tmp; return Find(Tag, tmp); @@ -552,9 +533,16 @@ signed int pkgTagSection::FindI(const char *Tag,signed long Default) const return Default; strncpy(S,Start,Stop-Start); S[Stop - Start] = 0; - + + errno = 0; char *End; signed long Result = strtol(S,&End,10); + if (errno == ERANGE) + _error->Errno("strtol", _("Cannot convert %s to integer"), S); + if (Result < std::numeric_limits<int>::min() || Result > std::numeric_limits<int>::max()) { + errno = ERANGE; + _error->Errno("", _("Cannot convert %s to integer"), S); + } if (S == End) return Default; return Result; @@ -598,6 +586,34 @@ bool pkgTagSection::FindB(const char *Tag, bool const &Default) const // TagSection::FindFlag - Locate a yes/no type flag /*{{{*/ // --------------------------------------------------------------------- /* The bits marked in Flag are masked on/off in Flags */ +bool pkgTagSection::FindFlag(const char * const Tag, uint8_t &Flags, + uint8_t const Flag) const +{ + const char *Start; + const char *Stop; + if (Find(Tag,Start,Stop) == false) + return true; + return FindFlag(Flags, Flag, Start, Stop); +} +bool pkgTagSection::FindFlag(uint8_t &Flags, uint8_t const Flag, + char const* const Start, char const* const Stop) +{ + switch (StringToBool(string(Start, Stop))) + { + case 0: + Flags &= ~Flag; + return true; + + case 1: + Flags |= Flag; + return true; + + default: + _error->Warning("Unknown flag value: %s",string(Start,Stop).c_str()); + return true; + } + return true; +} bool pkgTagSection::FindFlag(const char *Tag,unsigned long &Flags, unsigned long Flag) const { @@ -766,6 +782,14 @@ bool pkgTagSection::Write(FileFd &File, char const * const * const Order, std::v } /*}}}*/ +void pkgUserTagSection::TrimRecord(bool /*BeforeRecord*/, const char* &End)/*{{{*/ +{ + for (; Stop < End && (Stop[0] == '\n' || Stop[0] == '\r' || Stop[0] == '#'); Stop++) + if (Stop[0] == '#') + Stop = (const char*) memchr(Stop,'\n',End-Stop); +} + /*}}}*/ + #include "tagfile-order.c" // TFRewrite - Rewrite a control record /*{{{*/ diff --git a/apt-pkg/tagfile.h b/apt-pkg/tagfile.h index 118954541..19c07595e 100644 --- a/apt-pkg/tagfile.h +++ b/apt-pkg/tagfile.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: tagfile.h,v 1.20 2003/05/19 17:13:57 doogie Exp $ /* ###################################################################### Fast scanner for RFC-822 type header information @@ -38,17 +37,9 @@ class pkgTagSectionPrivate; class pkgTagSection { const char *Section; - // We have a limit of 256 tags per section with the old abi -#if APT_PKG_ABI < 413 - APT_DEPRECATED unsigned int Indexes[256]; -#endif unsigned int AlphaIndexes[0x100]; -#if APT_PKG_ABI < 413 - APT_DEPRECATED unsigned int TagCount; -#endif - // dpointer placeholder (for later in case we need it) - pkgTagSectionPrivate *d; + pkgTagSectionPrivate * const d; protected: const char *Stop; @@ -65,6 +56,10 @@ class pkgTagSection signed int FindI(const char *Tag,signed long Default = 0) const; bool FindB(const char *Tag, bool const &Default = false) const; unsigned long long FindULL(const char *Tag, unsigned long long const &Default = 0) const; + bool FindFlag(const char * const Tag,uint8_t &Flags, + uint8_t const Flag) const; + bool static FindFlag(uint8_t &Flags, uint8_t const Flag, + const char* const Start, const char* const Stop); bool FindFlag(const char *Tag,unsigned long &Flags, unsigned long Flag) const; bool static FindFlag(unsigned long &Flags, unsigned long Flag, @@ -86,12 +81,7 @@ class pkgTagSection * @return \b true if section end was found, \b false otherwise. * Beware that internal state will be inconsistent if \b false is returned! */ -#if APT_PKG_ABI >= 413 APT_MUSTCHECK bool Scan(const char *Start, unsigned long MaxLength, bool const Restart = true); -#else - APT_MUSTCHECK bool Scan(const char *Start, unsigned long MaxLength, bool const Restart); - APT_MUSTCHECK bool Scan(const char *Start, unsigned long MaxLength); -#endif inline unsigned long size() const {return Stop - Section;}; void Trim(); @@ -103,11 +93,7 @@ class pkgTagSection * times, but only the last occurrence is available via Find methods. */ unsigned int Count() const; -#if APT_PKG_ABI >= 413 bool Exists(const char* const Tag) const; -#else - bool Exists(const char* const Tag); -#endif void Get(const char *&Start,const char *&Stop,unsigned int I) const; @@ -138,16 +124,24 @@ class pkgTagSection * * @param File to write the section to * @param Order in which tags should appear in the file - * @param Rewrite is a set of tags to be renamed, rewitten and/or removed + * @param Rewrite is a set of tags to be renamed, rewritten and/or removed * @return \b true if successful, otherwise \b false */ bool Write(FileFd &File, char const * const * const Order = NULL, std::vector<Tag> const &Rewrite = std::vector<Tag>()) const; }; + +/* For user generated file the parser should be a bit more relaxed in exchange + for being a bit slower to allow comments and new lines all over the place */ +class pkgUserTagSection : public pkgTagSection +{ + virtual void TrimRecord(bool BeforeRecord, const char* &End) APT_OVERRIDE; +}; + class pkgTagFilePrivate; class pkgTagFile { - pkgTagFilePrivate *d; + pkgTagFilePrivate * const d; APT_HIDDEN bool Fill(); APT_HIDDEN bool Resize(); @@ -159,9 +153,9 @@ class pkgTagFile unsigned long Offset(); bool Jump(pkgTagSection &Tag,unsigned long long Offset); - void Init(FileFd *F,unsigned long long Size = 32*1024); + void Init(FileFd * const F,unsigned long long const Size = 32*1024); - pkgTagFile(FileFd *F,unsigned long long Size = 32*1024); + pkgTagFile(FileFd * const F,unsigned long long Size = 32*1024); virtual ~pkgTagFile(); }; diff --git a/apt-pkg/update.cc b/apt-pkg/update.cc index 2908a4820..369e85122 100644 --- a/apt-pkg/update.cc +++ b/apt-pkg/update.cc @@ -11,7 +11,6 @@ #include <apt-pkg/update.h> #include <string> -#include <vector> #include <apti18n.h> /*}}}*/ @@ -74,7 +73,7 @@ bool AcquireUpdate(pkgAcquire &Fetcher, int const PulseInterval, uri.User.clear(); uri.Password.clear(); string descUri = string(uri); - _error->Warning(_("Failed to fetch %s %s\n"), descUri.c_str(), + _error->Warning(_("Failed to fetch %s %s"), descUri.c_str(), (*I)->ErrorText.c_str()); if ((*I)->Status == pkgAcquire::Item::StatTransientNetworkError) diff --git a/apt-pkg/upgrade.cc b/apt-pkg/upgrade.cc index 6c8721da8..e7f2aae40 100644 --- a/apt-pkg/upgrade.cc +++ b/apt-pkg/upgrade.cc @@ -288,12 +288,6 @@ bool pkgMinimizeUpgrade(pkgDepCache &Cache) } /*}}}*/ // APT::Upgrade::Upgrade - Upgrade using a specific strategy /*{{{*/ -#if APT_PKG_ABI < 413 -bool APT::Upgrade::Upgrade(pkgDepCache &Cache, int mode) -{ - return Upgrade(Cache, mode, NULL); -} -#endif bool APT::Upgrade::Upgrade(pkgDepCache &Cache, int mode, OpProgress * const Progress) { APT_IGNORE_DEPRECATED_PUSH diff --git a/apt-pkg/upgrade.h b/apt-pkg/upgrade.h index 18b6aac7b..6cad64fd9 100644 --- a/apt-pkg/upgrade.h +++ b/apt-pkg/upgrade.h @@ -24,12 +24,7 @@ namespace APT { FORBID_INSTALL_NEW_PACKAGES = 2, ALLOW_EVERYTHING = 0 }; -#if APT_PKG_ABI >= 413 bool Upgrade(pkgDepCache &Cache, int UpgradeMode, OpProgress * const Progress = NULL); -#else - bool Upgrade(pkgDepCache &Cache, int UpgradeMode); - bool Upgrade(pkgDepCache &Cache, int UpgradeMode, OpProgress * const Progress); -#endif } } diff --git a/apt-pkg/vendor.cc b/apt-pkg/vendor.cc deleted file mode 100644 index d4add560e..000000000 --- a/apt-pkg/vendor.cc +++ /dev/null @@ -1,41 +0,0 @@ -#include<config.h> - -#include <apt-pkg/vendor.h> -#include <apt-pkg/configuration.h> - -#include <iostream> -#include <map> -#include <string> -#include <utility> -#include <vector> - -Vendor::Vendor(std::string VendorID, - std::string Origin, - std::vector<struct Vendor::Fingerprint *> *FingerprintList) -{ - this->VendorID = VendorID; - this->Origin = Origin; - for (std::vector<struct Vendor::Fingerprint *>::iterator I = FingerprintList->begin(); - I != FingerprintList->end(); ++I) - { - if (_config->FindB("Debug::Vendor", false)) - std::cerr << "Vendor \"" << VendorID << "\": Mapping \"" - << (*I)->Print << "\" to \"" << (*I)->Description << '"' << std::endl; - Fingerprints[(*I)->Print] = (*I)->Description; - } - delete FingerprintList; -} - -const std::string Vendor::LookupFingerprint(std::string Print) const -{ - std::map<std::string,std::string>::const_iterator Elt = Fingerprints.find(Print); - if (Elt == Fingerprints.end()) - return ""; - else - return (*Elt).second; -} - -APT_CONST bool Vendor::CheckDist(std::string /*Dist*/) -{ - return true; -} diff --git a/apt-pkg/vendor.h b/apt-pkg/vendor.h deleted file mode 100644 index 2d2e2b0ae..000000000 --- a/apt-pkg/vendor.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef PKGLIB_VENDOR_H -#define PKGLIB_VENDOR_H -#include <string> -#include <vector> -#include <map> - -#include <apt-pkg/macros.h> - -#ifndef APT_8_CLEANER_HEADERS -using std::string; -#endif - -// A class representing a particular software provider. -class APT_DEPRECATED Vendor -{ - public: - struct Fingerprint - { - std::string Print; - std::string Description; - }; - - protected: - std::string VendorID; - std::string Origin; - std::map<std::string, std::string> Fingerprints; - - public: - Vendor(std::string VendorID, std::string Origin, - std::vector<struct Fingerprint *> *FingerprintList); - virtual const std::string& GetVendorID() const { return VendorID; }; - virtual const std::string LookupFingerprint(std::string Print) const; - virtual bool CheckDist(std::string Dist); - virtual ~Vendor(){}; -}; - -#endif diff --git a/apt-pkg/vendorlist.cc b/apt-pkg/vendorlist.cc deleted file mode 100644 index db5b87fc0..000000000 --- a/apt-pkg/vendorlist.cc +++ /dev/null @@ -1,164 +0,0 @@ -#include<config.h> - -#include <apt-pkg/fileutl.h> -#include <apt-pkg/error.h> -#include <apt-pkg/configuration.h> - -#include <stddef.h> -#include <iostream> -#include <string> -#include <vector> - -#include <apti18n.h> - -// The whole vendor system is deprecated -APT_IGNORE_DEPRECATED_PUSH - -#include <apt-pkg/vendor.h> -#include <apt-pkg/vendorlist.h> - -using std::string; -using std::vector; - -pkgVendorList::~pkgVendorList() -{ - for (vector<const Vendor *>::const_iterator I = VendorList.begin(); - I != VendorList.end(); ++I) - delete *I; -} - -// pkgVendorList::ReadMainList - Read list of known package vendors /*{{{*/ -// --------------------------------------------------------------------- -/* This also scans a directory of vendor files similar to apt.conf.d - which can contain the usual suspects of distribution provided data. - The APT config mechanism allows the user to override these in their - configuration file. */ -bool pkgVendorList::ReadMainList() -{ - Configuration Cnf; - - string CnfFile = _config->FindDir("Dir::Etc::vendorparts"); - if (DirectoryExists(CnfFile) == true) - if (ReadConfigDir(Cnf,CnfFile,true) == false) - return false; - CnfFile = _config->FindFile("Dir::Etc::vendorlist"); - if (RealFileExists(CnfFile) == true) - if (ReadConfigFile(Cnf,CnfFile,true) == false) - return false; - - return CreateList(Cnf); -} - /*}}}*/ -bool pkgVendorList::Read(string File) /*{{{*/ -{ - Configuration Cnf; - if (ReadConfigFile(Cnf,File,true) == false) - return false; - - return CreateList(Cnf); -} - /*}}}*/ -bool pkgVendorList::CreateList(Configuration& Cnf) /*{{{*/ -{ - for (vector<const Vendor *>::const_iterator I = VendorList.begin(); - I != VendorList.end(); ++I) - delete *I; - VendorList.erase(VendorList.begin(),VendorList.end()); - - const Configuration::Item *Top = Cnf.Tree("Vendor"); - for (Top = (Top == 0?0:Top->Child); Top != 0; Top = Top->Next) - { - Configuration Block(Top); - string VendorID = Top->Tag; - vector <struct Vendor::Fingerprint *> *Fingerprints = new vector<Vendor::Fingerprint *>; - struct Vendor::Fingerprint *Fingerprint = new struct Vendor::Fingerprint(); - string Origin = Block.Find("Origin"); - - Fingerprint->Print = Block.Find("Fingerprint"); - Fingerprint->Description = Block.Find("Name"); - Fingerprints->push_back(Fingerprint); - - if (Fingerprint->Print.empty() || Fingerprint->Description.empty()) - { - _error->Error(_("Vendor block %s contains no fingerprint"), VendorID.c_str()); - delete Fingerprints; - continue; - } - if (_config->FindB("Debug::sourceList", false)) - std::cerr << "Adding vendor with ID: " << VendorID - << " Fingerprint: " << Fingerprint->Print << std::endl; - - VendorList.push_back(new Vendor(VendorID, Origin, Fingerprints)); - } - - /* Process 'group-key' type sections */ - Top = Cnf.Tree("group-key"); - for (Top = (Top == 0?0:Top->Child); Top != 0; Top = Top->Next) - { -// Configuration Block(Top); -// vector<Vendor::Fingerprint *> Fingerprints; -// string VendorID = Top->Tag; - -// while (Block->Next) -// { -// struct Vendor::Fingerprint Fingerprint = new struct Vendor::Fingerprint; -// Fingerprint->Print = Block.Find("Fingerprint"); -// Fingerprint->Description = Block.Find("Name"); -// if (Fingerprint->print.empty() || Fingerprint->Description.empty()) -// { -// _error->Error(_("Vendor block %s is invalid"), -// Vendor->VendorID.c_str()); -// delete Fingerprint; -// break; -// } -// Block = Block->Next->Next; -// } -// if (_error->PendingError()) -// { -// for (vector <struct Vendor::Fingerprint *>::iterator I = Fingerprints.begin(); -// I != Fingerprints.end(); I++) -// delete *I; -// delete Fingerprints; -// continue; -// } - -// VendorList.push_back(new Vendor(VendorID, Fingerprints)); - } - - return !_error->PendingError(); -} - /*}}}*/ -const Vendor* pkgVendorList::LookupFingerprint(string Fingerprint) /*{{{*/ -{ - for (const_iterator I = VendorList.begin(); I != VendorList.end(); ++I) - { - if ((*I)->LookupFingerprint(Fingerprint) != "") - return *I; - } - - return NULL; -} - /*}}}*/ -const Vendor* pkgVendorList::FindVendor(const std::vector<string> GPGVOutput) /*{{{*/ -{ - for (std::vector<string>::const_iterator I = GPGVOutput.begin(); I != GPGVOutput.end(); ++I) - { - string::size_type pos = (*I).find("VALIDSIG "); - if (_config->FindB("Debug::Vendor", false)) - std::cerr << "Looking for VALIDSIG in \"" << (*I) << "\": pos " << pos << std::endl; - if (pos != std::string::npos) - { - string Fingerprint = (*I).substr(pos+sizeof("VALIDSIG")); - if (_config->FindB("Debug::Vendor", false)) - std::cerr << "Looking for \"" << Fingerprint << "\" in vendor..." << std::endl; - const Vendor* vendor = this->LookupFingerprint(Fingerprint); - if (vendor != NULL) - return vendor; - } - } - - return NULL; -} - /*}}}*/ - -APT_IGNORE_DEPRECATED_POP diff --git a/apt-pkg/vendorlist.h b/apt-pkg/vendorlist.h deleted file mode 100644 index bc3702a93..000000000 --- a/apt-pkg/vendorlist.h +++ /dev/null @@ -1,54 +0,0 @@ -// -*- mode: cpp; mode: fold -*- -// Description /*{{{*/ -// $Id: vendorlist.h,v 1.1.2.1 2003/12/24 23:09:17 mdz Exp $ -/* ###################################################################### - - VendorList - Manage a list of vendors - - The Vendor List class provides access to a list of vendors and - attributes associated with them, read from a configuration file. - - ##################################################################### */ - /*}}}*/ -#ifndef PKGLIB_VENDORLIST_H -#define PKGLIB_VENDORLIST_H - -#include <string> -#include <vector> -#include <apt-pkg/macros.h> - -#ifndef APT_8_CLEANER_HEADERS -#include <apt-pkg/vendor.h> -#include <apt-pkg/configuration.h> -using std::string; -using std::vector; -#endif - -class Vendor; -class Configuration; - -class APT_DEPRECATED pkgVendorList -{ - protected: - std::vector<Vendor const *> VendorList; - - bool CreateList(Configuration& Cnf); - const Vendor* LookupFingerprint(std::string Fingerprint); - - public: - typedef std::vector<Vendor const *>::const_iterator const_iterator; - bool ReadMainList(); - bool Read(std::string File); - - // List accessors - inline const_iterator begin() const {return VendorList.begin();}; - inline const_iterator end() const {return VendorList.end();}; - inline unsigned int size() const {return VendorList.size();}; - inline bool empty() const {return VendorList.empty();}; - - const Vendor* FindVendor(const std::vector<std::string> GPGVOutput); - - ~pkgVendorList(); -}; - -#endif diff --git a/apt-pkg/version.cc b/apt-pkg/version.cc index 29bee46da..f32d39a69 100644 --- a/apt-pkg/version.cc +++ b/apt-pkg/version.cc @@ -40,3 +40,6 @@ pkgVersioningSystem *pkgVersioningSystem::GetVS(const char *Label) return 0; } /*}}}*/ + + +pkgVersioningSystem::~pkgVersioningSystem() {} diff --git a/apt-pkg/version.h b/apt-pkg/version.h index d98809f7e..5110ecaa7 100644 --- a/apt-pkg/version.h +++ b/apt-pkg/version.h @@ -55,7 +55,7 @@ class pkgVersioningSystem APT_MKSTRCMP(CmpReleaseVer,DoCmpReleaseVer); pkgVersioningSystem(); - virtual ~pkgVersioningSystem() {}; + virtual ~pkgVersioningSystem(); }; #endif diff --git a/apt-pkg/versionmatch.cc b/apt-pkg/versionmatch.cc index 284098bdf..2376ca8fd 100644 --- a/apt-pkg/versionmatch.cc +++ b/apt-pkg/versionmatch.cc @@ -137,7 +137,10 @@ pkgVersionMatch::pkgVersionMatch(string Data,MatchType Type) : Type(Type) // --------------------------------------------------------------------- /* */ bool pkgVersionMatch::MatchVer(const char *A,string B,bool Prefix) -{ +{ + if (A == NULL) + return false; + const char *Ab = A; const char *Ae = Ab + strlen(A); @@ -161,30 +164,45 @@ pkgCache::VerIterator pkgVersionMatch::Find(pkgCache::PkgIterator Pkg) pkgCache::VerIterator Ver = Pkg.VersionList(); for (; Ver.end() == false; ++Ver) { - if (Type == Version) - { - if (MatchVer(Ver.VerStr(),VerStr,VerPrefixMatch) == true) - return Ver; - if (ExpressionMatches(VerStr, Ver.VerStr()) == true) - return Ver; - continue; - } - - for (pkgCache::VerFileIterator VF = Ver.FileList(); VF.end() == false; ++VF) - if (FileMatch(VF.File()) == true) - return Ver; + if (VersionMatches(Ver)) + return Ver; } - + // This will be Ended by now. return Ver; } + /*}}}*/ + +// VersionMatch::Find - Locate the best match for the select type /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool pkgVersionMatch::VersionMatches(pkgCache::VerIterator Ver) +{ + if (Type == Version) + { + if (MatchVer(Ver.VerStr(),VerStr,VerPrefixMatch) == true) + return true; + if (ExpressionMatches(VerStr, Ver.VerStr()) == true) + return true; + return false; + } + + for (pkgCache::VerFileIterator VF = Ver.FileList(); VF.end() == false; ++VF) + if (FileMatch(VF.File()) == true) + return true; + + return false; +} + /*}}}*/ #ifndef FNM_CASEFOLD #define FNM_CASEFOLD 0 #endif -bool pkgVersionMatch::ExpressionMatches(const char *pattern, const char *string) +bool pkgVersionMatch::ExpressionMatches(const char *pattern, const char *string)/*{{{*/ { + if (pattern == NULL || string == NULL) + return false; if (pattern[0] == '/') { size_t length = strlen(pattern); if (pattern[length - 1] == '/') { @@ -230,38 +248,30 @@ bool pkgVersionMatch::FileMatch(pkgCache::PkgFileIterator File) return false; if (RelVerStr.empty() == false) - if (File->Version == 0 || - (MatchVer(File.Version(),RelVerStr,RelVerPrefixMatch) == false && - ExpressionMatches(RelVerStr, File.Version()) == false)) + if (MatchVer(File.Version(),RelVerStr,RelVerPrefixMatch) == false && + ExpressionMatches(RelVerStr, File.Version()) == false) return false; if (RelOrigin.empty() == false) - if (File->Origin == 0 || !ExpressionMatches(RelOrigin,File.Origin())) + if (!ExpressionMatches(RelOrigin,File.Origin())) return false; if (RelArchive.empty() == false) - if (File->Archive == 0 || - !ExpressionMatches(RelArchive,File.Archive())) + if (!ExpressionMatches(RelArchive,File.Archive())) return false; if (RelCodename.empty() == false) - if (File->Codename == 0 || - !ExpressionMatches(RelCodename,File.Codename())) + if (!ExpressionMatches(RelCodename,File.Codename())) return false; if (RelRelease.empty() == false) - if ((File->Archive == 0 || - !ExpressionMatches(RelRelease,File.Archive())) && - (File->Codename == 0 || - !ExpressionMatches(RelRelease,File.Codename()))) + if (!ExpressionMatches(RelRelease,File.Archive()) && + !ExpressionMatches(RelRelease,File.Codename())) return false; if (RelLabel.empty() == false) - if (File->Label == 0 || - !ExpressionMatches(RelLabel,File.Label())) + if (!ExpressionMatches(RelLabel,File.Label())) return false; if (RelComponent.empty() == false) - if (File->Component == 0 || - !ExpressionMatches(RelComponent,File.Component())) + if (!ExpressionMatches(RelComponent,File.Component())) return false; if (RelArchitecture.empty() == false) - if (File->Architecture == 0 || - !ExpressionMatches(RelArchitecture,File.Architecture())) + if (!ExpressionMatches(RelArchitecture,File.Architecture())) return false; return true; } @@ -269,11 +279,11 @@ bool pkgVersionMatch::FileMatch(pkgCache::PkgFileIterator File) if (Type == Origin) { if (OrSite.empty() == false) { - if (File->Site == 0) - return false; - } else // so we are talking about file:// or status file - if (strcmp(File.Site(),"") == 0 && File->Archive != 0 && strcmp(File.Archive(),"now") == 0) // skip the status file + if (File.Site() == NULL) return false; + } + else if (File->Release == 0)// only 'bad' files like dpkg.status file has no release file + return false; return (ExpressionMatches(OrSite, File.Site())); /* both strings match */ } diff --git a/apt-pkg/versionmatch.h b/apt-pkg/versionmatch.h index 4c8f704c8..156ad61cb 100644 --- a/apt-pkg/versionmatch.h +++ b/apt-pkg/versionmatch.h @@ -70,10 +70,11 @@ class pkgVersionMatch enum MatchType {None = 0,Version,Release,Origin} Type; bool MatchVer(const char *A,std::string B,bool Prefix) APT_PURE; - bool ExpressionMatches(const char *pattern, const char *string); - bool ExpressionMatches(const std::string& pattern, const char *string); + static bool ExpressionMatches(const char *pattern, const char *string); + static bool ExpressionMatches(const std::string& pattern, const char *string); bool FileMatch(pkgCache::PkgFileIterator File); pkgCache::VerIterator Find(pkgCache::PkgIterator Pkg); + bool VersionMatches(pkgCache::VerIterator Ver); pkgVersionMatch(std::string Data,MatchType Type); }; |