summaryrefslogtreecommitdiff
path: root/apt-pkg
diff options
context:
space:
mode:
authorDavid Kalnischkies <david@kalnischkies.de>2015-04-12 17:08:46 +0200
committerDavid Kalnischkies <david@kalnischkies.de>2015-04-19 01:13:10 +0200
commitba6b79bd0090077724fa1272ea4d3a31706fcd5a (patch)
tree020931e0a2e5316e2832b7c7bd4ee6d619a6db2d /apt-pkg
parent295d848b37e1211feae5d37db27f148dc9ea3d38 (diff)
a hit on Release files means the indexes will be hits too
If we get a IMSHit for the Transaction-Manager (= the InRelease file or as its still supported fallback Release + Release.gpg combo) we can assume that every file we would queue based on this manager, but already have locally is current and hence would get an IMSHit, too. We therefore save us and the server the trouble and skip the queuing in this case. Beside speeding up repetative executions of 'apt-get update' this way we also avoid hitting hashsum errors if the indexes are in fact already updated, but the Release file isn't yet as it is the case on well behaving mirrors as Release files is updated last. The implementation is a bit harder than the theory makes it sound as we still have to keep reverifying the Release files (e.g. to detect now expired once to avoid an attacker being able to silently stale us) and have to handle cases in which the Release file hits, but some indexes aren't present (e.g. user added a new foreign architecture).
Diffstat (limited to 'apt-pkg')
-rw-r--r--apt-pkg/acquire-item.cc90
-rw-r--r--apt-pkg/acquire-item.h28
-rw-r--r--apt-pkg/acquire.h1
3 files changed, 91 insertions, 28 deletions
diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc
index f30529066..750e7daca 100644
--- a/apt-pkg/acquire-item.cc
+++ b/apt-pkg/acquire-item.cc
@@ -213,7 +213,7 @@ void pkgAcquire::Item::Done(string Message,unsigned long long Size,HashStringLis
step */
bool pkgAcquire::Item::Rename(string From,string To)
{
- if (rename(From.c_str(),To.c_str()) == 0)
+ if (From == To || rename(From.c_str(),To.c_str()) == 0)
return true;
std::string S;
@@ -224,9 +224,41 @@ bool pkgAcquire::Item::Rename(string From,string To)
return false;
}
/*}}}*/
-void pkgAcquire::Item::QueueURI(ItemDesc &Item) /*{{{*/
+// 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() /*{{{*/
@@ -408,6 +440,14 @@ string pkgAcqDiffIndex::Custom600Headers()
return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
}
/*}}}*/
+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);
+}
+ /*}}}*/
bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile) /*{{{*/
{
// failing here is fine: our caller will take care of trying to
@@ -470,11 +510,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile) /*{{{*/
// we have the same sha1 as the server so we are done here
if(Debug)
std::clog << "pkgAcqDiffIndex: Package file " << CurrentPackagesFile << " is up-to-date" << std::endl;
-
- // 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);
+ QueueOnIMSHit();
return true;
}
@@ -1098,6 +1134,17 @@ 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)
{
@@ -1491,6 +1538,19 @@ void pkgAcqIndex::StageDecompressDone(string Message,
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), IndexTargets(IndexTargets),
+ AuthPass(false), RealURI(RealURI), IMSHit(false)
+{
+}
+ /*}}}*/
// AcqMetaBase::Add - Add a item to the current Transaction /*{{{*/
void pkgAcqMetaBase::Add(Item *I)
{
@@ -1831,13 +1891,7 @@ bool pkgAcqMetaBase::CheckAuthDone(string Message) /*{{{*/
std::cerr << "Signature verification succeeded: "
<< DestFile << std::endl;
- // Download further indexes with verification
- //
- // it would be really nice if we could simply do
- // if (IMSHit == false) QueueIndexes(true)
- // and skip the download if the Release file has not changed
- // - but right now the list cleaner will needs to be tricked
- // to not delete all our packages/source indexes in this case
+ // Download further indexes with verification
QueueIndexes(true);
return true;
@@ -1908,7 +1962,13 @@ bool pkgAcqMetaBase::CheckDownloadDone(const std::string &Message)
// make sure to verify against the right file on I-M-S hit
IMSHit = StringToBool(LookupTag(Message,"IMS-Hit"),false);
if(IMSHit)
+ {
+ // for simplicity, the transaction manager is always InRelease
+ // even if it doesn't exist.
+ if (TransactionManager != NULL)
+ TransactionManager->IMSHit = true;
DestFile = GetFinalFilename();
+ }
// set Item to complete as the remaining work is all local (verify etc)
Complete = true;
@@ -1951,7 +2011,7 @@ void pkgAcqMetaBase::QueueIndexes(bool verify) /*{{{*/
<< "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->MetaKeyFilename << std::endl;
+ std::cerr << "For: " << ((Record == NULL) ? "<NULL>" : Record->MetaKeyFilename) << std::endl;
}
if (verify == true && ExpectedIndexHashes.empty() == true)
diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h
index c2759b792..148728b3c 100644
--- a/apt-pkg/acquire-item.h
+++ b/apt-pkg/acquire-item.h
@@ -74,10 +74,15 @@ class pkgAcquire::Item : public WeakPointable
/** \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
*/
- void QueueURI(ItemDesc &Item);
+ virtual bool QueueURI(ItemDesc &Item);
/** \brief Remove this item from its owner's queue. */
void Dequeue();
@@ -392,9 +397,6 @@ class pkgAcqMetaBase : public pkgAcquire::Item /*{{{*/
*/
bool AuthPass;
- // required to deal gracefully with problems caused by incorrect ims hits
- bool IMSHit;
-
/** \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.
@@ -457,7 +459,11 @@ class pkgAcqMetaBase : public pkgAcquire::Item /*{{{*/
virtual std::string GetFinalFilename() const;
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);
// transaction code
void Add(Item *I);
@@ -479,10 +485,7 @@ class pkgAcqMetaBase : public pkgAcquire::Item /*{{{*/
indexRecords* MetaIndexParser,
std::string const &RealURI,
HashStringList const &ExpectedHashes=HashStringList(),
- pkgAcqMetaBase *TransactionManager=NULL)
- : Item(Owner, ExpectedHashes, TransactionManager),
- MetaIndexParser(MetaIndexParser), IndexTargets(IndexTargets),
- AuthPass(false), IMSHit(false), RealURI(RealURI) {};
+ pkgAcqMetaBase *TransactionManager=NULL);
};
/*}}}*/
/** \brief An acquire item that downloads the detached signature {{{
@@ -652,9 +655,7 @@ class pkgAcqBaseIndex : public pkgAcquire::Item
pkgAcqMetaBase *TransactionManager,
struct IndexTarget const * const Target,
HashStringList const &ExpectedHashes,
- indexRecords *MetaIndexParser)
- : Item(Owner, ExpectedHashes, TransactionManager), Target(Target),
- MetaIndexParser(MetaIndexParser) {};
+ indexRecords *MetaIndexParser);
};
/*}}}*/
/** \brief An item that is responsible for fetching an index file of {{{
@@ -691,6 +692,7 @@ class APT_HIDDEN pkgAcqDiffIndex : public pkgAcqBaseIndex
/** \brief Get the full pathname of the final file for the current URI */
virtual std::string GetFinalFilename() const;
+ virtual bool QueueURI(pkgAcquire::ItemDesc &Item);
public:
// Specialized action members
virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
@@ -714,7 +716,6 @@ class APT_HIDDEN pkgAcqDiffIndex : public pkgAcqBaseIndex
* false otherwise.
*/
bool ParseDiffIndex(std::string IndexDiffFile);
-
/** \brief Create a new pkgAcqDiffIndex.
*
@@ -733,6 +734,8 @@ class APT_HIDDEN pkgAcqDiffIndex : public pkgAcqBaseIndex
struct IndexTarget const * const Target,
HashStringList const &ExpectedHashes,
indexRecords *MetaIndexParser);
+ private:
+ APT_HIDDEN void QueueOnIMSHit() const;
};
/*}}}*/
/** \brief An item that is responsible for fetching client-merge patches {{{
@@ -1008,7 +1011,6 @@ class APT_HIDDEN pkgAcqIndex : public pkgAcqBaseIndex
virtual std::string GetFinalFilename() const;
public:
-
// Specialized action members
virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
virtual void Done(std::string Message,unsigned long long Size,
diff --git a/apt-pkg/acquire.h b/apt-pkg/acquire.h
index f33362922..fc90624e1 100644
--- a/apt-pkg/acquire.h
+++ b/apt-pkg/acquire.h
@@ -111,6 +111,7 @@ class pkgAcquire
struct MethodConfig;
struct ItemDesc;
friend class Item;
+ friend class pkgAcqMetaBase;
friend class Queue;
typedef std::vector<Item *>::iterator ItemIterator;