From c355ea30383486e74635cd0248d3b53ed9759c39 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 5 Nov 2014 18:04:29 +0100 Subject: reenable patchsize limit option for pdiffs One word: "doh!" Commit f6d4ab9ad8a2cfe52737ab620dd252cf8ceec43d disabled the check to prevent apt from downloading bigger patches than the index it tries to patch. Happens rarly of course, but still. Detected by scan-build complaining about a dead assignment. To make up for the mistake a test is included as well. --- apt-pkg/acquire-item.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 605ca7ae4..e0aef5874 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -619,7 +619,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile) /*{{{*/ cur != available_patches.end(); ++cur) patchesSize += cur->patch_size; unsigned long long const sizeLimit = ServerSize * _config->FindI("Acquire::PDiffs::SizeLimit", 100); - if (false && sizeLimit > 0 && (sizeLimit/100) < patchesSize) + if (sizeLimit > 0 && (sizeLimit/100) < patchesSize) { if (Debug) std::clog << "Need " << patchesSize << " bytes (Limit is " << sizeLimit/100 -- cgit v1.2.3 From ce105e87404c53c09b8f9af4f76736b50458f0c7 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 5 Nov 2014 18:26:01 +0100 Subject: (error) va_list 'args' was opened but not closed by va_end() The manpage of va_start and co additionally says: On some systems, va_end contains a closing '}' matching a '{' in va_start, so that both macros must occur in the same function, and in a way that allows this. So instead of return/breaking instantly, we save the return, make a proper turndown with va_end in all cases and only end after that. Reported-By: cppcheck Git-Dch: Ignore --- apt-pkg/contrib/strutl.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index ebf9c9ea6..0ac587a9e 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -1319,10 +1319,12 @@ void ioprintf(ostream &out,const char *format,...) va_list args; ssize_t size = 400; while (true) { + bool ret = false; va_start(args,format); - if (iovprintf(out, format, args, size) == true) - return; + ret = iovprintf(out, format, args, size); va_end(args); + if (ret == true) + return; } } void strprintf(string &out,const char *format,...) @@ -1331,10 +1333,12 @@ void strprintf(string &out,const char *format,...) ssize_t size = 400; std::ostringstream outstr; while (true) { + bool ret = false; va_start(args,format); - if (iovprintf(outstr, format, args, size) == true) - break; + ret = iovprintf(outstr, format, args, size); va_end(args); + if (ret == true) + break; } out = outstr.str(); } -- cgit v1.2.3 From 586d8704716a10e0f8b9c400cab500f5353eebe6 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 26 Oct 2014 23:17:03 +0100 Subject: replace ignore-deprecated #pragma dance with _Pragma For compatibility we use/provide and fill quiet some deprecated methods and fields, which subsequently earns us a warning for using them. These warnings therefore have to be disabled for these codeparts and that is what this change does now in a slightly more elegant way. Git-Dch: Ignore --- apt-pkg/acquire-item.cc | 18 ++----- apt-pkg/cacheset.cc | 46 ++++------------- apt-pkg/cacheset.h | 118 ++++++++++--------------------------------- apt-pkg/contrib/hashes.cc | 27 +++------- apt-pkg/contrib/hashes.h | 9 +--- apt-pkg/contrib/macros.h | 16 ++++++ apt-pkg/deb/debsrcrecords.cc | 20 +------- apt-pkg/indexrecords.cc | 9 +--- apt-pkg/indexrecords.h | 10 +--- apt-pkg/pkgcachegen.cc | 9 +--- apt-pkg/srcrecords.h | 10 +--- apt-pkg/upgrade.cc | 10 +--- apt-pkg/vendorlist.cc | 10 ++-- 13 files changed, 76 insertions(+), 236 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index e0aef5874..2df638a83 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -104,10 +104,7 @@ static bool AllowInsecureRepositories(indexRecords const * const MetaIndexParser // Acquire::Item::Item - Constructor /*{{{*/ -#if __GNUC__ >= 4 - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +APT_IGNORE_DEPRECATED_PUSH pkgAcquire::Item::Item(pkgAcquire *Owner, HashStringList const &ExpectedHashes, pkgAcqMetaBase *TransactionManager) @@ -120,9 +117,7 @@ pkgAcquire::Item::Item(pkgAcquire *Owner, if(TransactionManager != NULL) TransactionManager->Add(this); } -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif +APT_IGNORE_DEPRECATED_POP /*}}}*/ // Acquire::Item::~Item - Destructor /*{{{*/ // --------------------------------------------------------------------- @@ -275,14 +270,7 @@ bool pkgAcquire::Item::RenameOnError(pkgAcquire::Item::RenameOnErrorState const void pkgAcquire::Item::SetActiveSubprocess(const std::string &subprocess)/*{{{*/ { ActiveSubprocess = subprocess; -#if __GNUC__ >= 4 - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif - Mode = ActiveSubprocess.c_str(); -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif + APT_IGNORE_DEPRECATED(Mode = ActiveSubprocess.c_str();) } /*}}}*/ // Acquire::Item::ReportMirrorFailure /*{{{*/ diff --git a/apt-pkg/cacheset.cc b/apt-pkg/cacheset.cc index 76a7e717e..9127a4064 100644 --- a/apt-pkg/cacheset.cc +++ b/apt-pkg/cacheset.cc @@ -613,19 +613,14 @@ void CacheSetHelper::canNotFindPackage(enum PkgSelector const select, PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string const &pattern) { switch (select) { -#if __GNUC__ >= 4 - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +APT_IGNORE_DEPRECATED_PUSH case REGEX: canNotFindRegEx(pci, Cache, pattern); break; case TASK: canNotFindTask(pci, Cache, pattern); break; case FNMATCH: canNotFindFnmatch(pci, Cache, pattern); break; case PACKAGENAME: canNotFindPackage(pci, Cache, pattern); break; case STRING: canNotFindPackage(pci, Cache, pattern); break; case UNKNOWN: break; -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif +APT_IGNORE_DEPRECATED_POP } } // canNotFindTask - handle the case no package is found for a task /*{{{*/ @@ -663,19 +658,14 @@ pkgCache::PkgIterator CacheSetHelper::canNotFindPkgName(pkgCacheFile &Cache, void CacheSetHelper::canNotFindVersion(enum VerSelector const select, VersionContainerInterface * const vci, pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) { switch (select) { -#if __GNUC__ >= 4 - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +APT_IGNORE_DEPRECATED_PUSH case ALL: canNotFindAllVer(vci, Cache, Pkg); break; case INSTCAND: canNotFindInstCandVer(vci, Cache, Pkg); break; case CANDINST: canNotFindCandInstVer(vci, Cache, Pkg); break; case NEWEST: canNotFindNewestVer(Cache, Pkg); break; case CANDIDATE: canNotFindCandidateVer(Cache, Pkg); break; case INSTALLED: canNotFindInstalledVer(Cache, Pkg); break; -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif +APT_IGNORE_DEPRECATED_POP case CANDANDINST: canNotGetCandInstVer(Cache, Pkg); break; case RELEASE: case VERSIONNUMBER: @@ -706,16 +696,11 @@ void CacheSetHelper::canNotFindCandInstVer(VersionContainerInterface * const /*v // canNotGetVersion - for package by selector /*{{{*/ pkgCache::VerIterator CacheSetHelper::canNotGetVersion(enum VerSelector const select, pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) { switch (select) { -#if __GNUC__ >= 4 - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +APT_IGNORE_DEPRECATED_PUSH case NEWEST: return canNotFindNewestVer(Cache, Pkg); case CANDIDATE: return canNotFindCandidateVer(Cache, Pkg); case INSTALLED: return canNotFindInstalledVer(Cache, Pkg); -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif +APT_IGNORE_DEPRECATED_POP case CANDINST: return canNotGetCandInstVer(Cache, Pkg); case INSTCAND: return canNotGetInstCandVer(Cache, Pkg); case ALL: @@ -772,16 +757,11 @@ pkgCache::VerIterator CacheSetHelper::canNotGetCandInstVer(pkgCacheFile &Cache, APT_CONST void CacheSetHelper::showPackageSelection(pkgCache::PkgIterator const &pkg, enum PkgSelector const select, std::string const &pattern) { switch (select) { -#if __GNUC__ >= 4 - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +APT_IGNORE_DEPRECATED_PUSH case REGEX: showRegExSelection(pkg, pattern); break; case TASK: showTaskSelection(pkg, pattern); break; case FNMATCH: showFnmatchSelection(pkg, pattern); break; -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif +APT_IGNORE_DEPRECATED_POP case PACKAGENAME: /* no suprises here */ break; case STRING: /* handled by the special cases */ break; case UNKNOWN: break; @@ -807,20 +787,14 @@ APT_CONST void CacheSetHelper::showFnmatchSelection(pkgCache::PkgIterator const APT_CONST void CacheSetHelper::showVersionSelection(pkgCache::PkgIterator const &Pkg, pkgCache::VerIterator const &Ver, enum VerSelector const select, std::string const &pattern) { switch (select) { -#if __GNUC__ >= 4 - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +APT_IGNORE_DEPRECATED_PUSH case RELEASE: showSelectedVersion(Pkg, Ver, pattern, true); break; case VERSIONNUMBER: showSelectedVersion(Pkg, Ver, pattern, false); break; -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +APT_IGNORE_DEPRECATED_POP case NEWEST: case CANDIDATE: case INSTALLED: diff --git a/apt-pkg/cacheset.h b/apt-pkg/cacheset.h index f3f1d1fc6..884e8b859 100644 --- a/apt-pkg/cacheset.h +++ b/apt-pkg/cacheset.h @@ -23,6 +23,7 @@ #include #include #include +#include #ifndef APT_8_CLEANER_HEADERS #include @@ -224,14 +225,7 @@ public: inline std::string FullName(bool const Pretty) const { return getPkg().FullName(Pretty); } inline std::string FullName() const { return getPkg().FullName(); } APT_DEPRECATED inline const char *Section() const { -#if __GNUC__ >= 4 - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif - return getPkg().Section(); -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif + APT_IGNORE_DEPRECATED(return getPkg().Section();) } inline bool Purge() const {return getPkg().Purge(); } inline const char *Arch() const {return getPkg().Arch(); } @@ -261,14 +255,9 @@ public: REGEX = CacheSetHelper::REGEX, TASK = CacheSetHelper::TASK, FNMATCH = CacheSetHelper::FNMATCH }; -#if __GNUC__ >= 4 - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +APT_IGNORE_DEPRECATED_PUSH void setConstructor(Constructor const by) { ConstructedBy = (CacheSetHelper::PkgSelector)by; } -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif +APT_IGNORE_DEPRECATED_POP void setConstructor(CacheSetHelper::PkgSelector const by) { ConstructedBy = by; } CacheSetHelper::PkgSelector getConstructor() const { return ConstructedBy; } @@ -290,19 +279,14 @@ public: APT_DEPRECATED typedef CacheSetHelper::PkgModifier Modifier; -#if __GNUC__ >= 4 - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +APT_IGNORE_DEPRECATED_PUSH APT_DEPRECATED static pkgCache::PkgIterator FromName(pkgCacheFile &Cache, std::string const &pattern, CacheSetHelper &helper) { return helper.PackageFromName(Cache, pattern); } APT_DEPRECATED static bool FromModifierCommandLine(unsigned short &modID, PackageContainerInterface * const pci, pkgCacheFile &Cache, const char * cmdline, std::list const &mods, CacheSetHelper &helper) { return helper.PackageFromModifierCommandLine(modID, pci, Cache, cmdline, mods); } -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif +APT_IGNORE_DEPRECATED_POP private: CacheSetHelper::PkgSelector ConstructedBy; @@ -371,14 +355,9 @@ public: /*{{{*/ PackageContainer() : PackageContainerInterface() {} PackageContainer(CacheSetHelper::PkgSelector const &by) : PackageContainerInterface(by) {} -#if __GNUC__ >= 4 - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +APT_IGNORE_DEPRECATED_PUSH APT_DEPRECATED PackageContainer(Constructor const &by) : PackageContainerInterface((CacheSetHelper::PkgSelector)by) {} -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif +APT_IGNORE_DEPRECATED_POP /** \brief sort all included versions with given comparer @@ -439,10 +418,7 @@ public: /*{{{*/ return FromFnmatch(Cache, pattern, helper); } -#if __GNUC__ >= 4 - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +APT_IGNORE_DEPRECATED_PUSH /** \brief returns a package specified by a string \param Cache the package is in @@ -455,9 +431,7 @@ public: /*{{{*/ CacheSetHelper helper; return FromName(Cache, pattern, helper); } -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif +APT_IGNORE_DEPRECATED_POP /** \brief returns all packages specified by a string @@ -663,65 +637,45 @@ public: Modifier (unsigned short const &id, const char * const alias, Position const &pos, enum CacheSetHelper::VerSelector const select) : ID(id), Alias(alias), Pos(pos), SelectVersion(select) {} -#if __GNUC__ >= 4 - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +APT_IGNORE_DEPRECATED_PUSH APT_DEPRECATED Modifier(unsigned short const &id, const char * const alias, Position const &pos, Version const &select) : ID(id), Alias(alias), Pos(pos), SelectVersion((CacheSetHelper::VerSelector)select) {} -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif +APT_IGNORE_DEPRECATED_POP }; static bool FromCommandLine(VersionContainerInterface * const vci, pkgCacheFile &Cache, const char **cmdline, CacheSetHelper::VerSelector const fallback, CacheSetHelper &helper); -#if __GNUC__ >= 4 - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +APT_IGNORE_DEPRECATED_PUSH APT_DEPRECATED static bool FromCommandLine(VersionContainerInterface * const vci, pkgCacheFile &Cache, const char **cmdline, Version const &fallback, CacheSetHelper &helper) { return FromCommandLine(vci, Cache, cmdline, (CacheSetHelper::VerSelector)fallback, helper); } -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif +APT_IGNORE_DEPRECATED_POP static bool FromString(VersionContainerInterface * const vci, pkgCacheFile &Cache, std::string pkg, CacheSetHelper::VerSelector const fallback, CacheSetHelper &helper, bool const onlyFromName = false); -#if __GNUC__ >= 4 - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +APT_IGNORE_DEPRECATED_PUSH APT_DEPRECATED static bool FromString(VersionContainerInterface * const vci, pkgCacheFile &Cache, std::string pkg, Version const &fallback, CacheSetHelper &helper, bool const onlyFromName = false) { return FromString(vci, Cache, pkg, (CacheSetHelper::VerSelector)fallback, helper, onlyFromName); } -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif +APT_IGNORE_DEPRECATED_POP static bool FromPackage(VersionContainerInterface * const vci, pkgCacheFile &Cache, pkgCache::PkgIterator const &P, CacheSetHelper::VerSelector const fallback, CacheSetHelper &helper); -#if __GNUC__ >= 4 - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +APT_IGNORE_DEPRECATED_PUSH APT_DEPRECATED static bool FromPackage(VersionContainerInterface * const vci, pkgCacheFile &Cache, pkgCache::PkgIterator const &P, Version const &fallback, CacheSetHelper &helper) { return FromPackage(vci, Cache, P, (CacheSetHelper::VerSelector)fallback, helper); } -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif +APT_IGNORE_DEPRECATED_POP static bool FromModifierCommandLine(unsigned short &modID, VersionContainerInterface * const vci, @@ -735,10 +689,7 @@ public: pkgCache::DepIterator const &D, CacheSetHelper::VerSelector const selector, CacheSetHelper &helper); -#if __GNUC__ >= 4 - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +APT_IGNORE_DEPRECATED_PUSH APT_DEPRECATED static bool FromDependency(VersionContainerInterface * const vci, pkgCacheFile &Cache, pkgCache::DepIterator const &D, @@ -746,9 +697,7 @@ public: CacheSetHelper &helper) { return FromDependency(vci, Cache, D, (CacheSetHelper::VerSelector)selector, helper); } -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif +APT_IGNORE_DEPRECATED_POP protected: /*{{{*/ @@ -879,10 +828,7 @@ public: /*{{{*/ static VersionContainer FromString(pkgCacheFile &Cache, std::string pkg) { return FromString(Cache, pkg, CacheSetHelper::CANDINST); } -#if __GNUC__ >= 4 - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +APT_IGNORE_DEPRECATED_PUSH static VersionContainer FromCommandLine(pkgCacheFile &Cache, const char **cmdline, Version const &fallback, CacheSetHelper &helper) { VersionContainer vercon; @@ -906,9 +852,7 @@ public: /*{{{*/ CacheSetHelper helper; return FromString(Cache, pkg, (CacheSetHelper::VerSelector)fallback, helper); } -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif +APT_IGNORE_DEPRECATED_POP /** \brief returns all versions specified for the package @@ -927,10 +871,7 @@ public: /*{{{*/ CacheSetHelper helper; return FromPackage(Cache, P, fallback, helper); } -#if __GNUC__ >= 4 - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +APT_IGNORE_DEPRECATED_PUSH static VersionContainer FromPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &P, Version const &fallback, CacheSetHelper &helper) { VersionContainer vercon; @@ -942,9 +883,7 @@ public: /*{{{*/ CacheSetHelper helper; return FromPackage(Cache, P, (CacheSetHelper::VerSelector)fallback, helper); } -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif +APT_IGNORE_DEPRECATED_POP static VersionContainer FromPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &P) { return FromPackage(Cache, P, CacheSetHelper::CANDIDATE); } @@ -985,10 +924,7 @@ public: /*{{{*/ CacheSetHelper helper; return FromPackage(Cache, D, selector, helper); } -#if __GNUC__ >= 4 - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +APT_IGNORE_DEPRECATED_PUSH static VersionContainer FromDependency(pkgCacheFile &Cache, pkgCache::DepIterator const &D, Version const &selector, CacheSetHelper &helper) { VersionContainer vercon; @@ -1000,9 +936,7 @@ public: /*{{{*/ CacheSetHelper helper; return FromPackage(Cache, D, (CacheSetHelper::VerSelector)selector, helper); } -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif +APT_IGNORE_DEPRECATED_POP static VersionContainer FromDependency(pkgCacheFile &Cache, pkgCache::DepIterator const &D) { return FromPackage(Cache, D, CacheSetHelper::CANDIDATE); } diff --git a/apt-pkg/contrib/hashes.cc b/apt-pkg/contrib/hashes.cc index 55180c642..6e7080bc9 100644 --- a/apt-pkg/contrib/hashes.cc +++ b/apt-pkg/contrib/hashes.cc @@ -258,10 +258,7 @@ public: bool Hashes::Add(const unsigned char * const Data,unsigned long long const Size, unsigned int const Hashes) { bool Res = true; -#if __GNUC__ >= 4 - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +APT_IGNORE_DEPRECATED_PUSH if ((Hashes & MD5SUM) == MD5SUM) Res &= MD5.Add(Data, Size); if ((Hashes & SHA1SUM) == SHA1SUM) @@ -270,9 +267,7 @@ bool Hashes::Add(const unsigned char * const Data,unsigned long long const Size, Res &= SHA256.Add(Data, Size); if ((Hashes & SHA512SUM) == SHA512SUM) Res &= SHA512.Add(Data, Size); -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif +APT_IGNORE_DEPRECATED_POP d->FileSize += Size; return Res; } @@ -323,28 +318,18 @@ bool Hashes::AddFD(FileFd &Fd,unsigned long long Size, unsigned int const Hashes HashStringList Hashes::GetHashStringList() { HashStringList hashes; -#if __GNUC__ >= 4 - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +APT_IGNORE_DEPRECATED_PUSH hashes.push_back(HashString("MD5Sum", MD5.Result().Value())); hashes.push_back(HashString("SHA1", SHA1.Result().Value())); hashes.push_back(HashString("SHA256", SHA256.Result().Value())); hashes.push_back(HashString("SHA512", SHA512.Result().Value())); -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif +APT_IGNORE_DEPRECATED_POP std::string SizeStr; strprintf(SizeStr, "%llu", d->FileSize); hashes.push_back(HashString("Checksum-FileSize", SizeStr)); return hashes; } -#if __GNUC__ >= 4 - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +APT_IGNORE_DEPRECATED_PUSH Hashes::Hashes() { d = new PrivateHashes(); } Hashes::~Hashes() { delete d; } -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif +APT_IGNORE_DEPRECATED_POP diff --git a/apt-pkg/contrib/hashes.h b/apt-pkg/contrib/hashes.h index e2e213855..ca186d704 100644 --- a/apt-pkg/contrib/hashes.h +++ b/apt-pkg/contrib/hashes.h @@ -189,15 +189,10 @@ class Hashes HashStringList GetHashStringList(); -#if __GNUC__ >= 4 - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +APT_IGNORE_DEPRECATED_PUSH Hashes(); virtual ~Hashes(); -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif +APT_IGNORE_DEPRECATED_POP private: APT_HIDDEN APT_CONST inline unsigned int boolsToFlag(bool const addMD5, bool const addSHA1, bool const addSHA256, bool const addSHA512) diff --git a/apt-pkg/contrib/macros.h b/apt-pkg/contrib/macros.h index 3a5e37c63..c0af4b2c8 100644 --- a/apt-pkg/contrib/macros.h +++ b/apt-pkg/contrib/macros.h @@ -132,6 +132,22 @@ #endif #endif +#if __GNUC__ >= 4 + #define APT_IGNORE_DEPRECATED_PUSH \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") + #define APT_IGNORE_DEPRECATED_POP \ + _Pragma("GCC diagnostic pop") + #define APT_IGNORE_DEPRECATED(XXX) \ + APT_IGNORE_DEPRECATED_PUSH \ + XXX \ + APT_IGNORE_DEPRECATED_POP +#else + #define APT_IGNORE_DEPRECATED_PUSH + #define APT_IGNORE_DEPRECATED_POP + #define APT_IGNORE_DEPRECATED(XXX) XXX +#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. diff --git a/apt-pkg/deb/debsrcrecords.cc b/apt-pkg/deb/debsrcrecords.cc index 97f43aca2..d3c137bb9 100644 --- a/apt-pkg/deb/debsrcrecords.cc +++ b/apt-pkg/deb/debsrcrecords.cc @@ -170,16 +170,8 @@ bool debSrcRecordParser::Files(std::vector &List) // we have it already, store the new hash and be done if (file != List.end()) { -#if __GNUC__ >= 4 - // set for compatibility only, so warn users not us - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif if (checksumField == "Files") - file->MD5Hash = hash; -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif + APT_IGNORE_DEPRECATED(file->MD5Hash = hash;) // an error here indicates that we have two different hashes for the same file if (file->Hashes.push_back(hashString) == false) return _error->Error("Error parsing checksum in %s of source package %s", checksumField.c_str(), Package().c_str()); @@ -192,16 +184,8 @@ bool debSrcRecordParser::Files(std::vector &List) F.Size = strtoull(size.c_str(), NULL, 10); F.Hashes.push_back(hashString); -#if __GNUC__ >= 4 - // set for compatibility only, so warn users not us - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif if (checksumField == "Files") - F.MD5Hash = hash; -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif + APT_IGNORE_DEPRECATED(F.MD5Hash = hash;) // Try to guess what sort of file it is we are getting. string::size_type Pos = F.Path.length()-1; diff --git a/apt-pkg/indexrecords.cc b/apt-pkg/indexrecords.cc index e1e9ba657..0f27af32b 100644 --- a/apt-pkg/indexrecords.cc +++ b/apt-pkg/indexrecords.cc @@ -119,14 +119,7 @@ bool indexRecords::Load(const string Filename) /*{{{*/ std::string SizeStr; strprintf(SizeStr, "%llu", Size); Sum->Hashes.push_back(HashString("Checksum-FileSize", SizeStr)); -#if __GNUC__ >= 4 - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif - Sum->Hash = HashString(HashString::SupportedHashes()[i],Hash); -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif + APT_IGNORE_DEPRECATED(Sum->Hash = HashString(HashString::SupportedHashes()[i],Hash);) Entries[Name] = Sum; } Entries[Name]->Hashes.push_back(HashString(HashString::SupportedHashes()[i],Hash)); diff --git a/apt-pkg/indexrecords.h b/apt-pkg/indexrecords.h index 88a06779c..06b9dafa6 100644 --- a/apt-pkg/indexrecords.h +++ b/apt-pkg/indexrecords.h @@ -76,11 +76,7 @@ class indexRecords virtual ~indexRecords(); }; -#if __GNUC__ >= 4 - // ensure that con- & de-structor don't trigger this warning - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +APT_IGNORE_DEPRECATED_PUSH struct indexRecords::checkSum { std::string MetaKeyFilename; @@ -89,8 +85,6 @@ struct indexRecords::checkSum APT_DEPRECATED HashString Hash; }; -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif +APT_IGNORE_DEPRECATED_POP #endif diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index 9e6931fa6..a2c1c8760 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -668,14 +668,7 @@ bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name Grp->LastPackage = Package; // Set the name, arch and the ID -#if __GNUC__ >= 4 - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif - Pkg->Name = Grp->Name; -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif + 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); diff --git a/apt-pkg/srcrecords.h b/apt-pkg/srcrecords.h index c68d374bb..de2b6ff64 100644 --- a/apt-pkg/srcrecords.h +++ b/apt-pkg/srcrecords.h @@ -30,11 +30,7 @@ class pkgSrcRecords { public: -#if __GNUC__ >= 4 - // ensure that con- & de-structor don't trigger this warning - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +APT_IGNORE_DEPRECATED_PUSH // Describes a single file struct File { @@ -44,9 +40,7 @@ class pkgSrcRecords HashStringList Hashes; APT_DEPRECATED std::string MD5Hash; }; -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif +APT_IGNORE_DEPRECATED_POP // Abstract parser for each source record class Parser diff --git a/apt-pkg/upgrade.cc b/apt-pkg/upgrade.cc index ca670bdf5..41e76802a 100644 --- a/apt-pkg/upgrade.cc +++ b/apt-pkg/upgrade.cc @@ -282,11 +282,7 @@ bool pkgMinimizeUpgrade(pkgDepCache &Cache) // APT::Upgrade::Upgrade - Upgrade using a specific strategy /*{{{*/ bool APT::Upgrade::Upgrade(pkgDepCache &Cache, int mode, OpProgress * const Progress) { -#if __GNUC__ >= 4 - // the deprecated methods will become our privates, so that is fine - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +APT_IGNORE_DEPRECATED_PUSH if (mode == ALLOW_EVERYTHING) return pkgDistUpgrade(Cache, Progress); else if ((mode & ~FORBID_REMOVE_PACKAGES) == 0) @@ -295,9 +291,7 @@ bool APT::Upgrade::Upgrade(pkgDepCache &Cache, int mode, OpProgress * const Prog return pkgAllUpgradeNoNewPackages(Cache, Progress); else _error->Error("pkgAllUpgrade called with unsupported mode %i", mode); -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif +APT_IGNORE_DEPRECATED_POP return false; } /*}}}*/ diff --git a/apt-pkg/vendorlist.cc b/apt-pkg/vendorlist.cc index fb33ff17d..db5b87fc0 100644 --- a/apt-pkg/vendorlist.cc +++ b/apt-pkg/vendorlist.cc @@ -11,10 +11,8 @@ #include -#if __GNUC__ >= 4 - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +// The whole vendor system is deprecated +APT_IGNORE_DEPRECATED_PUSH #include #include @@ -163,6 +161,4 @@ const Vendor* pkgVendorList::FindVendor(const std::vector GPGVOutput) /* } /*}}}*/ -#if __GNUC__ >= 4 - #pragma GCC diagnostic pop -#endif +APT_IGNORE_DEPRECATED_POP -- cgit v1.2.3 From ccf6bdb3efc54165c76b42aae94c498a36acbe1b Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 7 Nov 2014 14:20:36 +0100 Subject: use a abi version check similar to the gcc check Git-Dch: Ignore --- apt-pkg/contrib/macros.h | 1 + apt-pkg/deb/deblistparser.cc | 2 +- apt-pkg/deb/deblistparser.h | 2 +- apt-pkg/deb/debmetaindex.cc | 2 +- apt-pkg/deb/debmetaindex.h | 2 +- apt-pkg/metaindex.h | 4 +++- apt-pkg/packagemanager.cc | 6 +++--- apt-pkg/packagemanager.h | 12 +++++------- apt-pkg/pkgcachegen.h | 2 +- 9 files changed, 17 insertions(+), 16 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/macros.h b/apt-pkg/contrib/macros.h index c0af4b2c8..14541d4d8 100644 --- a/apt-pkg/contrib/macros.h +++ b/apt-pkg/contrib/macros.h @@ -156,5 +156,6 @@ #define APT_PKG_MAJOR 4 #define APT_PKG_MINOR 15 #define APT_PKG_RELEASE 0 +#define APT_PKG_ABI ((APT_PKG_MAJOR * 100) + APT_PKG_MINOR) #endif diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 616d8296d..42db341b3 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -992,7 +992,7 @@ unsigned char debListParser::GetPrio(string Str) return Out; } /*}}}*/ -#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) +#if APT_PKG_ABI >= 413 bool debListParser::SameVersion(unsigned short const Hash, /*{{{*/ pkgCache::VerIterator const &Ver) { diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h index f20f7f33e..a757e69f1 100644 --- a/apt-pkg/deb/deblistparser.h +++ b/apt-pkg/deb/deblistparser.h @@ -71,7 +71,7 @@ class debListParser : public pkgCacheGenerator::ListParser virtual std::vector AvailableDescriptionLanguages(); virtual MD5SumValue Description_md5(); virtual unsigned short VersionHash(); -#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) +#if APT_PKG_ABI >= 413 virtual bool SameVersion(unsigned short const Hash, pkgCache::VerIterator const &Ver); #endif virtual bool UsePackage(pkgCache::PkgIterator &Pkg, diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index c103da8f7..a6c88b393 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -78,7 +78,7 @@ string debReleaseIndex::MetaIndexURI(const char *Type) const return Res; } -#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) +#if APT_PKG_ABI >= 0x0413 std::string debReleaseIndex::LocalFileName() const { // see if we have a InRelease file diff --git a/apt-pkg/deb/debmetaindex.h b/apt-pkg/deb/debmetaindex.h index 399543953..3d35401ec 100644 --- a/apt-pkg/deb/debmetaindex.h +++ b/apt-pkg/deb/debmetaindex.h @@ -53,7 +53,7 @@ class debReleaseIndex : public metaIndex { std::string MetaIndexFile(const char *Types) const; std::string MetaIndexURI(const char *Type) const; -#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) +#if APT_PKG_ABI >= 413 virtual std::string LocalFileName() const; #endif diff --git a/apt-pkg/metaindex.h b/apt-pkg/metaindex.h index 7c4d0c1aa..ae73c27dd 100644 --- a/apt-pkg/metaindex.h +++ b/apt-pkg/metaindex.h @@ -40,9 +40,11 @@ class metaIndex virtual const char* GetType() const {return Type;} // interface to to query it -#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) +#if APT_PKG_ABI >= 413 // returns the path of the local file (or "" if its not available) virtual std::string LocalFileName() const {return "";}; +#else + std::string LocalFileName() const; #endif // Interface for acquire diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc index 2247d04db..ba48c53cc 100644 --- a/apt-pkg/packagemanager.cc +++ b/apt-pkg/packagemanager.cc @@ -1059,7 +1059,7 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall() // PM::DoInstallPostFork - compat /*{{{*/ // --------------------------------------------------------------------- /*}}}*/ -#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) +#if APT_PKG_ABI >= 413 pkgPackageManager::OrderResult pkgPackageManager::DoInstallPostFork(int statusFd) { @@ -1096,7 +1096,7 @@ pkgPackageManager::DoInstallPostFork(int statusFd) // PM::DoInstall - Does the installation /*{{{*/ // --------------------------------------------------------------------- /* compat */ -#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) +#if APT_PKG_ABI >= 413 pkgPackageManager::OrderResult pkgPackageManager::DoInstall(int statusFd) { @@ -1120,7 +1120,7 @@ pkgPackageManager::OrderResult pkgPackageManager::DoInstall(int statusFd) // --------------------------------------------------------------------- /* This uses the filenames in FileNames and the information in the DepCache to perform the installation of packages.*/ -#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) +#if APT_PKG_ABI >= 413 pkgPackageManager::OrderResult pkgPackageManager::DoInstall(APT::Progress::PackageManager *progress) { diff --git a/apt-pkg/packagemanager.h b/apt-pkg/packagemanager.h index 5bcd2045d..fce0ad301 100644 --- a/apt-pkg/packagemanager.h +++ b/apt-pkg/packagemanager.h @@ -96,12 +96,10 @@ 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_MAJOR >= 4 && APT_PKG_MINOR >= 13) +#if APT_PKG_ABI >= 413 virtual bool Go(APT::Progress::PackageManager * /*progress*/) {return true;}; - virtual bool Go(int /*statusFd*/=-1) {return true;}; -#else - virtual bool Go(int /*statusFd*/=-1) {return true;}; #endif + virtual bool Go(int /*statusFd*/=-1) {return true;}; virtual void Reset() {}; @@ -114,8 +112,8 @@ class pkgPackageManager : protected pkgCache::Namespace bool GetArchives(pkgAcquire *Owner,pkgSourceList *Sources, pkgRecords *Recs); - // Do the installation -#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) + // Do the installation +#if APT_PKG_ABI >= 413 OrderResult DoInstall(APT::Progress::PackageManager *progress); // compat APT_DEPRECATED OrderResult DoInstall(int statusFd=-1); @@ -129,7 +127,7 @@ class pkgPackageManager : protected pkgCache::Namespace Res = OrderInstall(); return Res; }; -#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) +#if APT_PKG_ABI >= 413 // stuff that needs to be done after the fork OrderResult DoInstallPostFork(APT::Progress::PackageManager *progress); // compat diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h index 54c4f9e7a..93f30a703 100644 --- a/apt-pkg/pkgcachegen.h +++ b/apt-pkg/pkgcachegen.h @@ -178,7 +178,7 @@ class pkgCacheGenerator::ListParser * \param Hash of the currently parsed version * \param Ver to compare with */ -#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) +#if APT_PKG_ABI >= 413 virtual #endif APT_PURE bool SameVersion(unsigned short const Hash, pkgCache::VerIterator const &Ver); -- cgit v1.2.3 From f105aaba433f5a8b9c4326dd0d704501bf07d1e5 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 6 Nov 2014 12:53:59 +0100 Subject: better non-virtual metaIndex.LocalFileName() implementation We can't add a new virtual method without breaking the ABI, but we can freely add new methods, so for older ABIs we just implement this method with a dynamic_cast, so that clients can be more ignorant about the API here and especially don't need to pull a very dirty trick by assuming internal knowledge (like apt-get did here). --- apt-pkg/deb/debmetaindex.cc | 2 -- apt-pkg/deb/debmetaindex.h | 3 ++- apt-pkg/metaindex.cc | 40 ++++++++++++++++++++++++++++++++++++++++ apt-pkg/metaindex.h | 25 ++++++------------------- 4 files changed, 48 insertions(+), 22 deletions(-) create mode 100644 apt-pkg/metaindex.cc (limited to 'apt-pkg') diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index a6c88b393..d99fd8393 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -78,7 +78,6 @@ string debReleaseIndex::MetaIndexURI(const char *Type) const return Res; } -#if APT_PKG_ABI >= 0x0413 std::string debReleaseIndex::LocalFileName() const { // see if we have a InRelease file @@ -92,7 +91,6 @@ std::string debReleaseIndex::LocalFileName() const return ""; } -#endif string debReleaseIndex::IndexURISuffix(const char *Type, string const &Section, string const &Arch) const { diff --git a/apt-pkg/deb/debmetaindex.h b/apt-pkg/deb/debmetaindex.h index 3d35401ec..4a8e454c7 100644 --- a/apt-pkg/deb/debmetaindex.h +++ b/apt-pkg/deb/debmetaindex.h @@ -54,8 +54,9 @@ class debReleaseIndex : public metaIndex { std::string MetaIndexURI(const char *Type) const; #if APT_PKG_ABI >= 413 - virtual std::string LocalFileName() const; + 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; diff --git a/apt-pkg/metaindex.cc b/apt-pkg/metaindex.cc new file mode 100644 index 000000000..31a8ec009 --- /dev/null +++ b/apt-pkg/metaindex.cc @@ -0,0 +1,40 @@ +// Include Files /*{{{*/ +#include +#include + +#include + +#include +#include + /*}}}*/ + +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) +std::string metaIndex::LocalFileName() const { return ""; } +#else +#include +std::string metaIndex::LocalFileName() const +{ + debReleaseIndex const * deb = dynamic_cast(this); + if (deb != NULL) + return deb->LocalFileName(); + + return ""; +} +#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) +{ + /* nothing */ +} + +metaIndex::~metaIndex() +{ + if (Indexes == 0) + return; + for (std::vector::iterator I = (*Indexes).begin(); + I != (*Indexes).end(); ++I) + delete *I; + delete Indexes; +} diff --git a/apt-pkg/metaindex.h b/apt-pkg/metaindex.h index ae73c27dd..6c3d2880b 100644 --- a/apt-pkg/metaindex.h +++ b/apt-pkg/metaindex.h @@ -41,8 +41,8 @@ class metaIndex // interface to to query it #if APT_PKG_ABI >= 413 - // returns the path of the local file (or "" if its not available) - virtual std::string LocalFileName() const {return "";}; + /** \return the path of the local file (or "" if its not available) */ + virtual std::string LocalFileName() const; #else std::string LocalFileName() const; #endif @@ -50,25 +50,12 @@ class metaIndex // Interface for acquire virtual std::string ArchiveURI(std::string const& File) const = 0; virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false) const = 0; - virtual std::vector *GetIndexFiles() = 0; + virtual std::vector *GetIndexFiles() = 0; virtual bool IsTrusted() const = 0; - metaIndex(std::string const &URI, std::string const &Dist, - char const * const Type) - : Indexes(NULL), Type(Type), URI(URI), Dist(Dist), Trusted(false) - { - /* nothing */ - } - - virtual ~metaIndex() - { - if (Indexes == 0) - return; - for (std::vector::iterator I = (*Indexes).begin(); - I != (*Indexes).end(); ++I) - delete *I; - delete Indexes; - } + metaIndex(std::string const &URI, std::string const &Dist, + char const * const Type); + virtual ~metaIndex(); }; #endif -- cgit v1.2.3 From dce45dbe97531de6806707445da97d3f22285db8 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 6 Nov 2014 12:41:04 +0100 Subject: mark internal interfaces as hidden MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have a bunch of classes which are of no use for the outside world, but were still exported and so needed to preserve ABI/API. Marking them as hidden to not export them any longer is a big API break in theory, but in practice nobody is using them – as if they would its a bug. --- apt-pkg/acquire-item.h | 33 ++++++++++++++------------------- apt-pkg/deb/debindexfile.cc | 28 ++++++++++++++-------------- apt-pkg/deb/debindexfile.h | 14 +++++++------- apt-pkg/deb/deblistparser.h | 18 +++++++++--------- apt-pkg/deb/debmetaindex.cc | 15 ++++++++------- apt-pkg/deb/debmetaindex.h | 4 ++-- apt-pkg/deb/debrecords.h | 4 ++-- apt-pkg/deb/debsrcrecords.h | 4 ++-- apt-pkg/deb/debsystem.cc | 2 +- apt-pkg/edsp/edspindexfile.cc | 4 ++-- apt-pkg/edsp/edspindexfile.h | 2 +- apt-pkg/edsp/edsplistparser.h | 2 +- apt-pkg/edsp/edspsystem.cc | 4 ++-- apt-pkg/edsp/edspsystem.h | 4 +--- apt-pkg/init.cc | 2 +- apt-pkg/pkgcachegen.h | 10 +++++----- 16 files changed, 72 insertions(+), 78 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index 10d7e6a09..6fcb42c3a 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -342,7 +342,7 @@ class pkgAcquire::Item : public WeakPointable }; /*}}}*/ /** \brief Information about an index patch (aka diff). */ /*{{{*/ -struct DiffInfo { +struct APT_HIDDEN DiffInfo { /** The filename of the diff. */ std::string file; @@ -359,9 +359,7 @@ struct DiffInfo { unsigned long long patch_size; }; /*}}}*/ - /*}}}*/ - -class pkgAcqMetaBase : public pkgAcquire::Item +class pkgAcqMetaBase : public pkgAcquire::Item /*{{{*/ { void *d; @@ -441,12 +439,12 @@ class pkgAcqMetaBase : public pkgAcquire::Item bool TransactionHasError() APT_PURE; void CommitTransaction(); - /** \brief Stage (queue) a copy action when the transaction is commited + /** \brief Stage (queue) a copy action when the transaction is committed */ void TransactionStageCopy(Item *I, const std::string &From, const std::string &To); - /** \brief Stage (queue) a removal action when the transaction is commited + /** \brief Stage (queue) a removal action when the transaction is committed */ void TransactionStageRemoval(Item *I, const std::string &FinalFile); @@ -459,7 +457,7 @@ class pkgAcqMetaBase : public pkgAcquire::Item MetaIndexParser(MetaIndexParser), IndexTargets(IndexTargets), AuthPass(false), IMSHit(false) {}; }; - + /*}}}*/ /** \brief An acquire item that downloads the detached signature {{{ * of a meta-index (Release) file, then queues up the release * file itself. @@ -468,7 +466,7 @@ class pkgAcqMetaBase : public pkgAcquire::Item * * \sa pkgAcqMetaIndex */ -class pkgAcqMetaSig : public pkgAcqMetaBase +class APT_HIDDEN pkgAcqMetaSig : public pkgAcqMetaBase { void *d; @@ -512,7 +510,6 @@ class pkgAcqMetaSig : public pkgAcqMetaBase virtual ~pkgAcqMetaSig(); }; /*}}}*/ - /** \brief An item that is responsible for downloading the meta-index {{{ * file (i.e., Release) itself and verifying its signature. * @@ -523,7 +520,7 @@ class pkgAcqMetaSig : public pkgAcqMetaBase * otherwise, the expected hashsums will be "" (causing the * authentication of the index files to be bypassed). */ -class pkgAcqMetaIndex : public pkgAcqMetaBase +class APT_HIDDEN pkgAcqMetaIndex : public pkgAcqMetaBase { void *d; @@ -568,7 +565,7 @@ class pkgAcqMetaIndex : public pkgAcqMetaBase }; /*}}}*/ /** \brief An item repsonsible for downloading clearsigned metaindexes {{{*/ -class pkgAcqMetaClearSig : public pkgAcqMetaIndex +class APT_HIDDEN pkgAcqMetaClearSig : public pkgAcqMetaIndex { void *d; @@ -607,8 +604,6 @@ public: virtual ~pkgAcqMetaClearSig(); }; /*}}}*/ - - /** \brief Common base class for all classes that deal with fetching {{{ indexes */ @@ -652,7 +647,7 @@ class pkgAcqBaseIndex : public pkgAcquire::Item * * \sa pkgAcqIndexDiffs, pkgAcqIndex */ -class pkgAcqDiffIndex : public pkgAcqBaseIndex +class APT_HIDDEN pkgAcqDiffIndex : public pkgAcqBaseIndex { void *d; @@ -725,7 +720,7 @@ class pkgAcqDiffIndex : public pkgAcqBaseIndex * * \sa pkgAcqDiffIndex, pkgAcqIndex */ -class pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex +class APT_HIDDEN pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex { void *d; @@ -813,7 +808,7 @@ class pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex * * \sa pkgAcqDiffIndex, pkgAcqIndex */ -class pkgAcqIndexDiffs : public pkgAcqBaseIndex +class APT_HIDDEN pkgAcqIndexDiffs : public pkgAcqBaseIndex { void *d; @@ -929,7 +924,7 @@ class pkgAcqIndexDiffs : public pkgAcqBaseIndex * * \todo Why does pkgAcqIndex have protected members? */ -class pkgAcqIndex : public pkgAcqBaseIndex +class APT_HIDDEN pkgAcqIndex : public pkgAcqBaseIndex { void *d; @@ -1028,7 +1023,7 @@ class pkgAcqIndex : public pkgAcqBaseIndex }; /*}}}*/ /** \brief Information about an index file. */ /*{{{*/ -class IndexTarget +class APT_HIDDEN IndexTarget { void *d; @@ -1053,7 +1048,7 @@ class IndexTarget }; /*}}}*/ /** \brief Information about an optional index file. */ /*{{{*/ -class OptionalIndexTarget : public IndexTarget +class APT_HIDDEN OptionalIndexTarget : public IndexTarget { void *d; diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index 335f9d36e..cecfe41a9 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -802,13 +802,13 @@ pkgSrcRecords::Parser *debDscFileIndex::CreateSrcParser() const } /*}}}*/ // Index File types for Debian /*{{{*/ -class debIFTypeSrc : public pkgIndexFile::Type +class APT_HIDDEN debIFTypeSrc : public pkgIndexFile::Type { public: debIFTypeSrc() {Label = "Debian Source Index";}; }; -class debIFTypePkg : public pkgIndexFile::Type +class APT_HIDDEN debIFTypePkg : public pkgIndexFile::Type { public: @@ -818,12 +818,12 @@ class debIFTypePkg : public pkgIndexFile::Type }; debIFTypePkg() {Label = "Debian Package Index";}; }; -class debIFTypeTrans : public debIFTypePkg +class APT_HIDDEN debIFTypeTrans : public debIFTypePkg { public: debIFTypeTrans() {Label = "Debian Translation Index";}; }; -class debIFTypeStatus : public pkgIndexFile::Type +class APT_HIDDEN debIFTypeStatus : public pkgIndexFile::Type { public: @@ -833,7 +833,7 @@ class debIFTypeStatus : public pkgIndexFile::Type }; debIFTypeStatus() {Label = "Debian dpkg status file";}; }; -class debIFTypeDebPkgFile : public pkgIndexFile::Type +class APT_HIDDEN debIFTypeDebPkgFile : public pkgIndexFile::Type { public: virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const @@ -842,7 +842,7 @@ class debIFTypeDebPkgFile : public pkgIndexFile::Type }; debIFTypeDebPkgFile() {Label = "deb Package file";}; }; -class debIFTypeDscFile : public pkgIndexFile::Type +class APT_HIDDEN debIFTypeDscFile : public pkgIndexFile::Type { public: virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string DscFile) const @@ -851,7 +851,7 @@ class debIFTypeDscFile : public pkgIndexFile::Type }; debIFTypeDscFile() {Label = "dsc File Source Index";}; }; -class debIFTypeDebianSourceDir : public pkgIndexFile::Type +class APT_HIDDEN debIFTypeDebianSourceDir : public pkgIndexFile::Type { public: virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string SourceDir) const @@ -861,14 +861,14 @@ class debIFTypeDebianSourceDir : public pkgIndexFile::Type debIFTypeDebianSourceDir() {Label = "debian/control File Source Index";}; }; -static debIFTypeSrc _apt_Src; -static debIFTypePkg _apt_Pkg; -static debIFTypeTrans _apt_Trans; -static debIFTypeStatus _apt_Status; -static debIFTypeDebPkgFile _apt_DebPkgFile; +APT_HIDDEN debIFTypeSrc _apt_Src; +APT_HIDDEN debIFTypePkg _apt_Pkg; +APT_HIDDEN debIFTypeTrans _apt_Trans; +APT_HIDDEN debIFTypeStatus _apt_Status; +APT_HIDDEN debIFTypeDebPkgFile _apt_DebPkgFile; // file based pseudo indexes -static debIFTypeDscFile _apt_DscFile; -static debIFTypeDebianSourceDir _apt_DebianSourceDir; +APT_HIDDEN debIFTypeDscFile _apt_DscFile; +APT_HIDDEN debIFTypeDebianSourceDir _apt_DebianSourceDir; const pkgIndexFile::Type *debSourcesIndex::GetType() const { diff --git a/apt-pkg/deb/debindexfile.h b/apt-pkg/deb/debindexfile.h index d727d9547..312e915f1 100644 --- a/apt-pkg/deb/debindexfile.h +++ b/apt-pkg/deb/debindexfile.h @@ -28,7 +28,7 @@ class pkgAcquire; class pkgCacheGenerator; -class debStatusIndex : public pkgIndexFile +class APT_HIDDEN debStatusIndex : public pkgIndexFile { /** \brief dpointer placeholder (for later in case we need it) */ void *d; @@ -55,7 +55,7 @@ class debStatusIndex : public pkgIndexFile virtual ~debStatusIndex(); }; -class debPackagesIndex : public pkgIndexFile +class APT_HIDDEN debPackagesIndex : public pkgIndexFile { /** \brief dpointer placeholder (for later in case we need it) */ void *d; @@ -92,7 +92,7 @@ class debPackagesIndex : public pkgIndexFile virtual ~debPackagesIndex(); }; -class debTranslationsIndex : public pkgIndexFile +class APT_HIDDEN debTranslationsIndex : public pkgIndexFile { /** \brief dpointer placeholder (for later in case we need it) */ void *d; @@ -126,7 +126,7 @@ class debTranslationsIndex : public pkgIndexFile virtual ~debTranslationsIndex(); }; -class debSourcesIndex : public pkgIndexFile +class APT_HIDDEN debSourcesIndex : public pkgIndexFile { /** \brief dpointer placeholder (for later in case we need it) */ void *d; @@ -163,7 +163,7 @@ class debSourcesIndex : public pkgIndexFile virtual ~debSourcesIndex(); }; -class debDebPkgFileIndex : public pkgIndexFile +class APT_HIDDEN debDebPkgFileIndex : public pkgIndexFile { private: void *d; @@ -193,7 +193,7 @@ class debDebPkgFileIndex : public pkgIndexFile virtual ~debDebPkgFileIndex(); }; -class debDscFileIndex : public pkgIndexFile +class APT_HIDDEN debDscFileIndex : public pkgIndexFile { private: std::string DscFile; @@ -211,7 +211,7 @@ class debDscFileIndex : public pkgIndexFile virtual ~debDscFileIndex() {}; }; -class debDebianSourceDirIndex : public debDscFileIndex +class APT_HIDDEN debDebianSourceDirIndex : public debDscFileIndex { public: virtual const Type *GetType() const APT_CONST; diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h index a757e69f1..6279d8399 100644 --- a/apt-pkg/deb/deblistparser.h +++ b/apt-pkg/deb/deblistparser.h @@ -26,7 +26,7 @@ class FileFd; -class debListParser : public pkgCacheGenerator::ListParser +class APT_HIDDEN debListParser : public pkgCacheGenerator::ListParser { public: @@ -59,7 +59,7 @@ class debListParser : public pkgCacheGenerator::ListParser public: - static unsigned char GetPrio(std::string Str); + APT_PUBLIC static unsigned char GetPrio(std::string Str); // These all operate against the current section virtual std::string Package(); @@ -84,26 +84,26 @@ class debListParser : public pkgCacheGenerator::ListParser bool LoadReleaseInfo(pkgCache::PkgFileIterator &FileI,FileFd &File, std::string section); - static const char *ParseDepends(const char *Start,const char *Stop, + APT_PUBLIC static const char *ParseDepends(const char *Start,const char *Stop, std::string &Package,std::string &Ver,unsigned int &Op); - static const char *ParseDepends(const char *Start,const char *Stop, + APT_PUBLIC static const char *ParseDepends(const char *Start,const char *Stop, std::string &Package,std::string &Ver,unsigned int &Op, bool const &ParseArchFlags); - static const char *ParseDepends(const char *Start,const char *Stop, + APT_PUBLIC static const char *ParseDepends(const char *Start,const char *Stop, std::string &Package,std::string &Ver,unsigned int &Op, bool const &ParseArchFlags, bool const &StripMultiArch); - static const char *ParseDepends(const char *Start,const char *Stop, + APT_PUBLIC static const char *ParseDepends(const char *Start,const char *Stop, std::string &Package,std::string &Ver,unsigned int &Op, bool const &ParseArchFlags, bool const &StripMultiArch, bool const &ParseRestrictionsList); - static const char *ConvertRelation(const char *I,unsigned int &Op); + APT_PUBLIC static const char *ConvertRelation(const char *I,unsigned int &Op); debListParser(FileFd *File, std::string const &Arch = ""); virtual ~debListParser(); }; -class debDebFileParser : public debListParser +class APT_HIDDEN debDebFileParser : public debListParser { private: std::string DebFile; @@ -114,7 +114,7 @@ class debDebFileParser : public debListParser pkgCache::VerIterator &Ver); }; -class debTranslationsParser : public debListParser +class APT_HIDDEN debTranslationsParser : public debListParser { public: // a translation can never be a real package diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index d99fd8393..81e067424 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -392,7 +392,7 @@ debReleaseIndex::debSectionEntry::debSectionEntry (string const &Section, bool const &IsSrc): Section(Section), IsSrc(IsSrc) {} -class debSLTypeDebian : public pkgSourceList::Type +class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type { protected: @@ -484,7 +484,7 @@ debDebFileMetaIndex::debDebFileMetaIndex(std::string const &DebFile) } -class debSLTypeDeb : public debSLTypeDebian +class APT_HIDDEN debSLTypeDeb : public debSLTypeDebian { public: @@ -502,7 +502,7 @@ class debSLTypeDeb : public debSLTypeDebian } }; -class debSLTypeDebSrc : public debSLTypeDebian +class APT_HIDDEN debSLTypeDebSrc : public debSLTypeDebian { public: @@ -520,7 +520,7 @@ class debSLTypeDebSrc : public debSLTypeDebian } }; -class debSLTypeDebFile : public pkgSourceList::Type +class APT_HIDDEN debSLTypeDebFile : public pkgSourceList::Type { public: @@ -539,6 +539,7 @@ class debSLTypeDebFile : public pkgSourceList::Type Label = "Debian Deb File"; } }; -debSLTypeDeb _apt_DebType; -debSLTypeDebSrc _apt_DebSrcType; -debSLTypeDebFile _apt_DebFileType; + +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 4a8e454c7..94d005760 100644 --- a/apt-pkg/deb/debmetaindex.h +++ b/apt-pkg/deb/debmetaindex.h @@ -21,7 +21,7 @@ class pkgIndexFile; class debDebPkgFileIndex; class IndexTarget; -class debReleaseIndex : public metaIndex { +class APT_HIDDEN debReleaseIndex : public metaIndex { public: class debSectionEntry @@ -74,7 +74,7 @@ class debReleaseIndex : public metaIndex { void PushSectionEntry(const debSectionEntry *Entry); }; -class debDebFileMetaIndex : public metaIndex +class APT_HIDDEN debDebFileMetaIndex : public metaIndex { private: std::string DebFile; diff --git a/apt-pkg/deb/debrecords.h b/apt-pkg/deb/debrecords.h index 6b5f94334..7091c38e6 100644 --- a/apt-pkg/deb/debrecords.h +++ b/apt-pkg/deb/debrecords.h @@ -25,7 +25,7 @@ #include #endif -class debRecordParser : public pkgRecords::Parser +class APT_HIDDEN debRecordParser : public pkgRecords::Parser { /** \brief dpointer placeholder (for later in case we need it) */ void *d; @@ -64,7 +64,7 @@ class debRecordParser : public pkgRecords::Parser }; // custom record parser that reads deb files directly -class debDebFileRecordParser : public debRecordParser +class APT_HIDDEN debDebFileRecordParser : public debRecordParser { public: virtual std::string FileName() { diff --git a/apt-pkg/deb/debsrcrecords.h b/apt-pkg/deb/debsrcrecords.h index a0a151875..1a09f6546 100644 --- a/apt-pkg/deb/debsrcrecords.h +++ b/apt-pkg/deb/debsrcrecords.h @@ -21,7 +21,7 @@ class pkgIndexFile; -class debSrcRecordParser : public pkgSrcRecords::Parser +class APT_HIDDEN debSrcRecordParser : public pkgSrcRecords::Parser { /** \brief dpointer placeholder (for later in case we need it) */ void *d; @@ -61,7 +61,7 @@ class debSrcRecordParser : public pkgSrcRecords::Parser virtual ~debSrcRecordParser(); }; -class debDscRecordParser : public debSrcRecordParser +class APT_HIDDEN debDscRecordParser : public debSrcRecordParser { public: debDscRecordParser(std::string const &DscFile, pkgIndexFile const *Index); diff --git a/apt-pkg/deb/debsystem.cc b/apt-pkg/deb/debsystem.cc index 142f3a6e6..9a5da9da1 100644 --- a/apt-pkg/deb/debsystem.cc +++ b/apt-pkg/deb/debsystem.cc @@ -38,7 +38,7 @@ using std::string; debSystem debSys; -class debSystemPrivate { +class APT_HIDDEN debSystemPrivate { public: debSystemPrivate() : LockFD(-1), LockCount(0), StatusFile(0) { diff --git a/apt-pkg/edsp/edspindexfile.cc b/apt-pkg/edsp/edspindexfile.cc index c38f24567..d00536362 100644 --- a/apt-pkg/edsp/edspindexfile.cc +++ b/apt-pkg/edsp/edspindexfile.cc @@ -65,7 +65,7 @@ bool edspIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const } /*}}}*/ // Index File types for APT /*{{{*/ -class edspIFType: public pkgIndexFile::Type +class APT_HIDDEN edspIFType: public pkgIndexFile::Type { public: virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator) const @@ -75,7 +75,7 @@ class edspIFType: public pkgIndexFile::Type }; edspIFType() {Label = "EDSP scenario file";}; }; -static edspIFType _apt_Universe; +APT_HIDDEN edspIFType _apt_Universe; const pkgIndexFile::Type *edspIndex::GetType() const { diff --git a/apt-pkg/edsp/edspindexfile.h b/apt-pkg/edsp/edspindexfile.h index 609a2cde4..8c18d8cbd 100644 --- a/apt-pkg/edsp/edspindexfile.h +++ b/apt-pkg/edsp/edspindexfile.h @@ -18,7 +18,7 @@ class OpProgress; class pkgCacheGenerator; -class edspIndex : public debStatusIndex +class APT_HIDDEN edspIndex : public debStatusIndex { /** \brief dpointer placeholder (for later in case we need it) */ void *d; diff --git a/apt-pkg/edsp/edsplistparser.h b/apt-pkg/edsp/edsplistparser.h index 959fb587f..86cd77606 100644 --- a/apt-pkg/edsp/edsplistparser.h +++ b/apt-pkg/edsp/edsplistparser.h @@ -25,7 +25,7 @@ class FileFd; -class edspListParser : public debListParser +class APT_HIDDEN edspListParser : public debListParser { public: virtual bool NewVersion(pkgCache::VerIterator &Ver); diff --git a/apt-pkg/edsp/edspsystem.cc b/apt-pkg/edsp/edspsystem.cc index 92edb8d77..063517421 100644 --- a/apt-pkg/edsp/edspsystem.cc +++ b/apt-pkg/edsp/edspsystem.cc @@ -26,8 +26,6 @@ #include /*}}}*/ -edspSystem edspSys; - // System::debSystem - Constructor /*{{{*/ edspSystem::edspSystem() { @@ -126,3 +124,5 @@ bool edspSystem::FindIndex(pkgCache::PkgFileIterator File, return false; } /*}}}*/ + +APT_HIDDEN edspSystem edspSys; diff --git a/apt-pkg/edsp/edspsystem.h b/apt-pkg/edsp/edspsystem.h index 65e36d714..06a63f40c 100644 --- a/apt-pkg/edsp/edspsystem.h +++ b/apt-pkg/edsp/edspsystem.h @@ -22,7 +22,7 @@ class pkgIndexFile; class pkgPackageManager; class edspIndex; -class edspSystem : public pkgSystem +class APT_HIDDEN edspSystem : public pkgSystem { /** \brief dpointer placeholder (for later in case we need it) */ void *d; @@ -45,6 +45,4 @@ class edspSystem : public pkgSystem ~edspSystem(); }; -extern edspSystem edspSys; - #endif diff --git a/apt-pkg/init.cc b/apt-pkg/init.cc index d04c51621..f756eab26 100644 --- a/apt-pkg/init.cc +++ b/apt-pkg/init.cc @@ -89,7 +89,7 @@ bool pkgInitConfig(Configuration &Cnf) Cnf.Set("Dir::Ignore-Files-Silently::", "\\.distUpgrade$"); // Repository security - // FIXME: this is set to "true" for backward compatiblity, once + // FIXME: this is set to "true" for backward compatibility, once // jessie is out we want to change this to "false" to // improve security Cnf.CndSet("Acquire::AllowInsecureRepositories", true); diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h index 93f30a703..c4ace713d 100644 --- a/apt-pkg/pkgcachegen.h +++ b/apt-pkg/pkgcachegen.h @@ -34,7 +34,7 @@ class pkgSourceList; class OpProgress; class pkgIndexFile; -class pkgCacheGenerator /*{{{*/ +class APT_HIDDEN pkgCacheGenerator /*{{{*/ { private: APT_HIDDEN map_stringitem_t WriteStringInMap(std::string const &String) { return WriteStringInMap(String.c_str()); }; @@ -111,10 +111,10 @@ class pkgCacheGenerator /*{{{*/ bool MergeFileProvides(ListParser &List); bool FinishCache(OpProgress *Progress) APT_DEPRECATED APT_CONST; - static bool MakeStatusCache(pkgSourceList &List,OpProgress *Progress, + APT_PUBLIC static bool MakeStatusCache(pkgSourceList &List,OpProgress *Progress, MMap **OutMap = 0,bool AllowMem = false); - static bool MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **OutMap); - static DynamicMMap* CreateDynamicMMap(FileFd *CacheF, unsigned long Flags = 0); + 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); @@ -136,7 +136,7 @@ class pkgCacheGenerator /*{{{*/ }; /*}}}*/ // This is the abstract package list parser class. /*{{{*/ -class pkgCacheGenerator::ListParser +class APT_HIDDEN pkgCacheGenerator::ListParser { pkgCacheGenerator *Owner; friend class pkgCacheGenerator; -- cgit v1.2.3 From 765190e493645e13b5651625d87fd9c8db910a85 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 7 Nov 2014 16:45:18 +0100 Subject: guard ABI changes for SourcePkg/Ver in pkgCache Git-Dch: Ignore --- apt-pkg/cacheiterators.h | 2 ++ apt-pkg/deb/deblistparser.cc | 2 ++ apt-pkg/deb/dpkgpm.cc | 11 ++++++++++- apt-pkg/edsp.cc | 7 +++++++ apt-pkg/pkgcache.h | 2 ++ 5 files changed, 23 insertions(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h index b0c02d4a2..f8f4c05ce 100644 --- a/apt-pkg/cacheiterators.h +++ b/apt-pkg/cacheiterators.h @@ -215,12 +215,14 @@ class pkgCache::VerIterator : public Iterator { // 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"; diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 42db341b3..462818a03 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -141,6 +141,7 @@ 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; @@ -192,6 +193,7 @@ bool debListParser::NewVersion(pkgCache::VerIterator &Ver) } } } +#endif Ver->MultiArch = ParseMultiArch(true); // Archive Size diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 0cded32e1..3f6039e0d 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1684,7 +1684,7 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg) if (apportPkg.end() == true || apportPkg->CurrentVer == 0) return; - string pkgname, reportfile, srcpkgname, pkgver, arch; + string pkgname, reportfile, pkgver, arch; string::size_type pos; FILE *report; @@ -1823,7 +1823,16 @@ 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/edsp.cc b/apt-pkg/edsp.cc index 2ba914b16..3c6a7e30f 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -96,7 +96,14 @@ void EDSP::WriteScenarioVersion(pkgDepCache &Cache, FILE* output, pkgCache::PkgI 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) diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h index 4f8568205..a7b7fa539 100644 --- a/apt-pkg/pkgcache.h +++ b/apt-pkg/pkgcache.h @@ -510,12 +510,14 @@ 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 */ -- cgit v1.2.3 From 02e20767719873fa8f1919bd0e7a75f63e00c484 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 7 Nov 2014 17:49:36 +0100 Subject: guard const-ification API changes Git-Dch: Ignore --- apt-pkg/acquire-item.cc | 28 ++++++++++++++++++++++++++++ apt-pkg/acquire-item.h | 41 ++++++++++++++++++++++++++++++++++++++++- apt-pkg/contrib/hashes.h | 2 ++ apt-pkg/pkgrecords.h | 7 +++++++ apt-pkg/tagfile.cc | 4 ++++ apt-pkg/tagfile.h | 4 ++++ 6 files changed, 85 insertions(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 2df638a83..dd85fda79 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -373,7 +373,11 @@ pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner, // 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 Final = _config->FindDir("Dir::State::lists"); Final += URItoFileName(Desc.URI); @@ -1239,7 +1243,11 @@ 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(); @@ -1638,7 +1646,11 @@ pkgAcqMetaSig::~pkgAcqMetaSig() /*{{{*/ /*}}}*/ // pkgAcqMetaSig::Custom600Headers - Insert custom request headers /*{{{*/ // --------------------------------------------------------------------- +#if APT_PKG_ABI >= 413 string pkgAcqMetaSig::Custom600Headers() const +#else +string pkgAcqMetaSig::Custom600Headers() +#endif { std::string Header = GetCustom600Headers(RealURI); return Header; @@ -1783,7 +1795,11 @@ void pkgAcqMetaIndex::Init(std::string URIDesc, std::string ShortDesc) /*}}}*/ // pkgAcqMetaIndex::Custom600Headers - Insert custom request headers /*{{{*/ // --------------------------------------------------------------------- +#if APT_PKG_ABI >= 413 string pkgAcqMetaIndex::Custom600Headers() const +#else +string pkgAcqMetaIndex::Custom600Headers() +#endif { return GetCustom600Headers(RealURI); } @@ -2107,7 +2123,11 @@ pkgAcqMetaClearSig::~pkgAcqMetaClearSig() /*{{{*/ /*}}}*/ // pkgAcqMetaClearSig::Custom600Headers - Insert custom request headers /*{{{*/ // --------------------------------------------------------------------- +#if APT_PKG_ABI >= 413 string pkgAcqMetaClearSig::Custom600Headers() const +#else +string pkgAcqMetaClearSig::Custom600Headers() +#endif { string Header = GetCustom600Headers(RealURI); Header += "\nFail-Ignore: true"; @@ -2499,7 +2519,11 @@ 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 { return Trusted; } @@ -2644,7 +2668,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 { if (IsIndexFile) return "\nIndex-File: true"; diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index 6fcb42c3a..1af737e00 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -254,7 +254,11 @@ 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 /** \brief A "descriptive" URI-like string. * @@ -280,9 +284,16 @@ class pkgAcquire::Item : public WeakPointable /** \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 /** \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 /** \brief Report mirror problem * @@ -497,7 +508,11 @@ class APT_HIDDEN pkgAcqMetaSig : public pkgAcqMetaBase 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 RealURI; }; /** \brief Create a new pkgAcqMetaSig. */ @@ -551,7 +566,11 @@ class APT_HIDDEN pkgAcqMetaIndex : public pkgAcqMetaBase 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 RealURI; }; virtual void Finished(); @@ -589,7 +608,11 @@ class APT_HIDDEN pkgAcqMetaClearSig : public pkgAcqMetaIndex 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); @@ -675,7 +698,11 @@ class APT_HIDDEN pkgAcqDiffIndex : public pkgAcqBaseIndex 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 /** \brief Parse the Index file for a set of Packages diffs. * @@ -989,7 +1016,11 @@ class APT_HIDDEN pkgAcqIndex : public pkgAcqBaseIndex 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. @@ -1111,8 +1142,12 @@ class pkgAcqArchive : public pkgAcquire::Item 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 + /** \brief Create a new pkgAcqArchive. * * \param Owner The pkgAcquire object with which this item is @@ -1161,7 +1196,11 @@ class pkgAcqFile : public pkgAcquire::Item 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 /** \brief Create a new pkgAcqFile object. * diff --git a/apt-pkg/contrib/hashes.h b/apt-pkg/contrib/hashes.h index ca186d704..154862457 100644 --- a/apt-pkg/contrib/hashes.h +++ b/apt-pkg/contrib/hashes.h @@ -55,6 +55,8 @@ class HashString // get hash type used std::string HashType() const { return Type; }; std::string HashValue() const { return Hash; }; + APT_DEPRECATED std::string HashType() { return Type; }; + APT_DEPRECATED std::string HashValue() { return Hash; }; // verify the given filename against the currently loaded hash bool VerifyFile(std::string filename) const; diff --git a/apt-pkg/pkgrecords.h b/apt-pkg/pkgrecords.h index a902da8b8..bcc05baba 100644 --- a/apt-pkg/pkgrecords.h +++ b/apt-pkg/pkgrecords.h @@ -68,10 +68,17 @@ 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();}; diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc index b263baf66..e667c495f 100644 --- a/apt-pkg/tagfile.cc +++ b/apt-pkg/tagfile.cc @@ -408,7 +408,11 @@ 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); diff --git a/apt-pkg/tagfile.h b/apt-pkg/tagfile.h index 4cd99b2fc..99e2a8d93 100644 --- a/apt-pkg/tagfile.h +++ b/apt-pkg/tagfile.h @@ -97,7 +97,11 @@ 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 inline void Get(const char *&Start,const char *&Stop,unsigned int I) const {Start = Section + Tags[I].StartTag; Stop = Section + Tags[I+1].StartTag;} -- cgit v1.2.3 From fa5404ab01bdf06eaf147d9f133139e6c89b906a Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 7 Nov 2014 18:18:14 +0100 Subject: explicit overload methods instead of adding parameters Adding a new parameter (with a default) is an ABI break, but you can overload a method, which is "just" an API break for everyone doing references to this method (aka: nobody). Git-Dch: Ignore --- apt-pkg/algorithms.cc | 12 ++++++++++++ apt-pkg/algorithms.h | 10 ++++++++++ apt-pkg/contrib/configuration.cc | 6 ++++++ apt-pkg/contrib/configuration.h | 8 ++++++++ apt-pkg/depcache.h | 4 ++-- apt-pkg/indexrecords.cc | 13 +++++++++++++ apt-pkg/indexrecords.h | 6 +++++- apt-pkg/tagfile.cc | 6 ++++++ apt-pkg/tagfile.h | 6 ++++++ apt-pkg/upgrade.cc | 18 ++++++++++++++++-- apt-pkg/upgrade.h | 13 +++++++++---- 11 files changed, 93 insertions(+), 9 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 71b5ac2c1..c8696b8ad 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -640,6 +640,12 @@ 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"); @@ -1138,6 +1144,12 @@ 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"); diff --git a/apt-pkg/algorithms.h b/apt-pkg/algorithms.h index b6da1f2bf..2ac28c0d7 100644 --- a/apt-pkg/algorithms.h +++ b/apt-pkg/algorithms.h @@ -138,10 +138,20 @@ 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(); diff --git a/apt-pkg/contrib/configuration.cc b/apt-pkg/contrib/configuration.cc index 4380d64b9..483d5bb1b 100644 --- a/apt-pkg/contrib/configuration.cc +++ b/apt-pkg/contrib/configuration.cc @@ -253,6 +253,12 @@ 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 Configuration::FindVector(const char *Name) const +{ + return FindVector(Name, ""); +} +#endif vector Configuration::FindVector(const char *Name, std::string const &Default) const { vector Vec; diff --git a/apt-pkg/contrib/configuration.h b/apt-pkg/contrib/configuration.h index 2ecea8bee..8d7d51037 100644 --- a/apt-pkg/contrib/configuration.h +++ b/apt-pkg/contrib/configuration.h @@ -84,8 +84,16 @@ class Configuration * * \param Name of the parent node * \param Default list of values separated by commas */ +#if APT_PKG_ABI >= 413 std::vector FindVector(const char *Name, std::string const &Default = "") const; std::vector FindVector(std::string const &Name, std::string const &Default = "") const { return FindVector(Name.c_str(), Default); }; +#else + std::vector FindVector(const char *Name, std::string const &Default) const; + std::vector FindVector(std::string const &Name, std::string const &Default) const { return FindVector(Name.c_str(), Default); }; + std::vector FindVector(const char *Name) const; + std::vector FindVector(std::string const &Name) const { return FindVector(Name.c_str(), ""); }; +#endif + 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);}; bool FindB(const char *Name,bool const &Default = false) const; diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h index 5554e1a69..20d263c67 100644 --- a/apt-pkg/depcache.h +++ b/apt-pkg/depcache.h @@ -109,7 +109,7 @@ class pkgDepCache : protected pkgCache::Namespace * * \return \b false if an error occurred. */ - APT_HIDDEN bool MarkRequired(InRootSetFunc &rootFunc); + bool MarkRequired(InRootSetFunc &rootFunc); /** \brief Set the StateCache::Garbage flag on all packages that * should be removed. @@ -120,7 +120,7 @@ class pkgDepCache : protected pkgCache::Namespace * * \return \b false if an error occurred. */ - APT_HIDDEN bool Sweep(); + bool Sweep(); public: diff --git a/apt-pkg/indexrecords.cc b/apt-pkg/indexrecords.cc index 0f27af32b..d65266f64 100644 --- a/apt-pkg/indexrecords.cc +++ b/apt-pkg/indexrecords.cc @@ -270,10 +270,23 @@ void indexRecords::SetTrusted(bool const Trusted) 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 index 06b9dafa6..35e534c12 100644 --- a/apt-pkg/indexrecords.h +++ b/apt-pkg/indexrecords.h @@ -42,8 +42,12 @@ class indexRecords std::map 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); diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc index e667c495f..3ee5c7076 100644 --- a/apt-pkg/tagfile.cc +++ b/apt-pkg/tagfile.cc @@ -281,6 +281,12 @@ pkgTagSection::pkgTagSection() } /*}}}*/ // 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; diff --git a/apt-pkg/tagfile.h b/apt-pkg/tagfile.h index 99e2a8d93..ac6d42089 100644 --- a/apt-pkg/tagfile.h +++ b/apt-pkg/tagfile.h @@ -86,7 +86,13 @@ 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(); virtual void TrimRecord(bool BeforeRecord, const char* &End); diff --git a/apt-pkg/upgrade.cc b/apt-pkg/upgrade.cc index 41e76802a..6c8721da8 100644 --- a/apt-pkg/upgrade.cc +++ b/apt-pkg/upgrade.cc @@ -24,7 +24,7 @@ The problem resolver is used to resolve the problems. */ -bool pkgDistUpgrade(pkgDepCache &Cache, OpProgress * const Progress) +static bool pkgDistUpgrade(pkgDepCache &Cache, OpProgress * const Progress) { std::string const solver = _config->Find("APT::Solver", "internal"); if (solver != "internal") @@ -119,6 +119,10 @@ bool pkgDistUpgrade(pkgDepCache &Cache, OpProgress * const Progress) if (Progress != NULL) Progress->Done(); return success; +} +bool pkgDistUpgrade(pkgDepCache &Cache) +{ + return pkgDistUpgrade(Cache, NULL); } /*}}}*/ // AllUpgradeNoNewPackages - Upgrade but no removals or new pkgs /*{{{*/ @@ -229,9 +233,13 @@ static bool pkgAllUpgradeWithNewPackages(pkgDepCache &Cache, OpProgress * const /* Right now the system must be consistent before this can be called. It also will not change packages marked for install, it only tries to install packages not marked for install */ -bool pkgAllUpgrade(pkgDepCache &Cache, OpProgress * const Progress) +static bool pkgAllUpgrade(pkgDepCache &Cache, OpProgress * const Progress) { return pkgAllUpgradeNoNewPackages(Cache, Progress); +} +bool pkgAllUpgrade(pkgDepCache &Cache) +{ + return pkgAllUpgrade(Cache, NULL); } /*}}}*/ // MinimizeUpgrade - Minimizes the set of packages to be upgraded /*{{{*/ @@ -280,6 +288,12 @@ 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 a3f693d86..18b6aac7b 100644 --- a/apt-pkg/upgrade.h +++ b/apt-pkg/upgrade.h @@ -20,17 +20,22 @@ namespace APT { namespace Upgrade { // FIXME: make this "enum class UpgradeMode {" once we enable c++11 enum UpgradeMode { - ALLOW_EVERYTHING = 0, FORBID_REMOVE_PACKAGES = 1, - FORBID_INSTALL_NEW_PACKAGES = 2 + 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 } } // please use APT::Upgrade::Upgrade() instead -APT_DEPRECATED bool pkgDistUpgrade(pkgDepCache &Cache, OpProgress * const Progress = NULL); -APT_DEPRECATED bool pkgAllUpgrade(pkgDepCache &Cache, OpProgress * const Progress = NULL); +APT_DEPRECATED bool pkgDistUpgrade(pkgDepCache &Cache); +APT_DEPRECATED bool pkgAllUpgrade(pkgDepCache &Cache); bool pkgMinimizeUpgrade(pkgDepCache &Cache); #endif -- cgit v1.2.3 From 32ab4bd05cb298f6bf1f9574f5b20570beaae429 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 7 Nov 2014 19:18:21 +0100 Subject: guard pkg/grp hashtable creation changes The change itself is no problem ABI wise, but the remove of the old undynamic hashtables is, so we bring it back for older abis and happily use the now available free space to backport more recent additions like the dynamic hashtable itself. Git-Dch: Ignore --- apt-pkg/pkgcache.cc | 39 ++++++++++++--------- apt-pkg/pkgcache.h | 93 ++++++++++++++++++++++++++++++++++++++++++-------- apt-pkg/pkgcachegen.cc | 18 +++++----- 3 files changed, 110 insertions(+), 40 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index 572685ba5..8d6e242b1 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -82,10 +82,13 @@ pkgCache::Header::Header() MaxDescFileSize = 0; FileList = 0; +#if APT_PKG_ABI < 413 + APT_IGNORE_DEPRECATED(StringList = 0;) +#endif VerSysName = 0; Architecture = 0; - Architectures = 0; - HashTableSize = _config->FindI("APT::Cache-HashTableSize", 10 * 1048); + SetArchitectures(0); + SetHashTableSize(_config->FindI("APT::Cache-HashTableSize", 10 * 1048)); memset(Pools,0,sizeof(Pools)); CacheFileSize = 0; @@ -114,6 +117,7 @@ bool pkgCache::Header::CheckSizes(Header &Against) const // Cache::pkgCache - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ +APT_IGNORE_DEPRECATED_PUSH pkgCache::pkgCache(MMap *Map, bool DoMap) : Map(*Map) { // call getArchitectures() with cached=false to ensure that the @@ -123,6 +127,7 @@ pkgCache::pkgCache(MMap *Map, bool DoMap) : Map(*Map) if (DoMap == true) ReMap(); } +APT_IGNORE_DEPRECATED_POP /*}}}*/ // Cache::ReMap - Reopen the cache file /*{{{*/ // --------------------------------------------------------------------- @@ -162,7 +167,7 @@ bool pkgCache::ReMap(bool const &Errorchecks) if (Map.Size() < HeaderP->CacheFileSize) return _error->Error(_("The package cache file is corrupted, it is too small")); - if (HeaderP->VerSysName == 0 || HeaderP->Architecture == 0 || HeaderP->Architectures == 0) + if (HeaderP->VerSysName == 0 || HeaderP->Architecture == 0 || HeaderP->GetArchitectures() == 0) return _error->Error(_("The package cache file is corrupted")); // Locate our VS.. @@ -176,8 +181,8 @@ bool pkgCache::ReMap(bool const &Errorchecks) for (++a; a != archs.end(); ++a) list.append(",").append(*a); if (_config->Find("APT::Architecture") != StrP + HeaderP->Architecture || - list != StrP + HeaderP->Architectures) - return _error->Error(_("The package cache was built for different architectures: %s vs %s"), StrP + HeaderP->Architectures, list.c_str()); + list != StrP + HeaderP->GetArchitectures()) + return _error->Error(_("The package cache was built for different architectures: %s vs %s"), StrP + HeaderP->GetArchitectures(), list.c_str()); return true; } @@ -192,7 +197,7 @@ map_id_t pkgCache::sHash(const string &Str) const unsigned long Hash = 0; for (string::const_iterator I = Str.begin(); I != Str.end(); ++I) Hash = 41 * Hash + tolower_ascii(*I); - return Hash % HeaderP->HashTableSize; + return Hash % HeaderP->GetHashTableSize(); } map_id_t pkgCache::sHash(const char *Str) const @@ -200,7 +205,7 @@ map_id_t pkgCache::sHash(const char *Str) const unsigned long Hash = tolower_ascii(*Str); for (const char *I = Str + 1; *I != 0; ++I) Hash = 41 * Hash + tolower_ascii(*I); - return Hash % HeaderP->HashTableSize; + return Hash % HeaderP->GetHashTableSize(); } /*}}}*/ // Cache::SingleArchFindPkg - Locate a package by name /*{{{*/ @@ -211,8 +216,8 @@ map_id_t pkgCache::sHash(const char *Str) const pkgCache::PkgIterator pkgCache::SingleArchFindPkg(const string &Name) { // Look at the hash bucket - Package *Pkg = PkgP + HeaderP->PkgHashTable()[Hash(Name)]; - for (; Pkg != PkgP; Pkg = PkgP + Pkg->Next) + Package *Pkg = PkgP + HeaderP->PkgHashTableP()[Hash(Name)]; + for (; Pkg != PkgP; Pkg = PkgP + Pkg->NextPackage) { int const cmp = strcmp(Name.c_str(), StrP + (GrpP + Pkg->Group)->Name); if (cmp == 0) @@ -273,7 +278,7 @@ pkgCache::GrpIterator pkgCache::FindGrp(const string &Name) { return GrpIterator(*this,0); // Look at the hash bucket for the group - Group *Grp = GrpP + HeaderP->GrpHashTable()[sHash(Name)]; + Group *Grp = GrpP + HeaderP->GrpHashTableP()[sHash(Name)]; for (; Grp != GrpP; Grp = GrpP + Grp->Next) { int const cmp = strcmp(Name.c_str(), StrP + Grp->Name); if (cmp == 0) @@ -359,7 +364,7 @@ pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) const { // Iterate over the list to find the matching arch for (pkgCache::Package *Pkg = PackageList(); Pkg != Owner->PkgP; - Pkg = Owner->PkgP + Pkg->Next) { + Pkg = Owner->PkgP + Pkg->NextPackage) { if (stringcmp(Arch, Owner->StrP + Pkg->Arch) == 0) return PkgIterator(*Owner, Pkg); if ((Owner->PkgP + S->LastPackage) == Pkg) @@ -407,7 +412,7 @@ pkgCache::PkgIterator pkgCache::GrpIterator::NextPkg(pkgCache::PkgIterator const if (S->LastPackage == LastPkg.Index()) return PkgIterator(*Owner, 0); - return PkgIterator(*Owner, Owner->PkgP + LastPkg->Next); + return PkgIterator(*Owner, Owner->PkgP + LastPkg->NextPackage); } /*}}}*/ // GrpIterator::operator ++ - Postfix incr /*{{{*/ @@ -420,10 +425,10 @@ void pkgCache::GrpIterator::operator ++(int) S = Owner->GrpP + S->Next; // Follow the hash table - while (S == Owner->GrpP && (HashIndex+1) < (signed)Owner->HeaderP->HashTableSize) + while (S == Owner->GrpP && (HashIndex+1) < (signed)Owner->HeaderP->GetHashTableSize()) { HashIndex++; - S = Owner->GrpP + Owner->HeaderP->GrpHashTable()[HashIndex]; + S = Owner->GrpP + Owner->HeaderP->GrpHashTableP()[HashIndex]; } } /*}}}*/ @@ -434,13 +439,13 @@ void pkgCache::PkgIterator::operator ++(int) { // Follow the current links if (S != Owner->PkgP) - S = Owner->PkgP + S->Next; + S = Owner->PkgP + S->NextPackage; // Follow the hash table - while (S == Owner->PkgP && (HashIndex+1) < (signed)Owner->HeaderP->HashTableSize) + while (S == Owner->PkgP && (HashIndex+1) < (signed)Owner->HeaderP->GetHashTableSize()) { HashIndex++; - S = Owner->PkgP + Owner->HeaderP->PkgHashTable()[HashIndex]; + S = Owner->PkgP + Owner->HeaderP->PkgHashTableP()[HashIndex]; } } /*}}}*/ diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h index a7b7fa539..2ba23c5c0 100644 --- a/apt-pkg/pkgcache.h +++ b/apt-pkg/pkgcache.h @@ -85,16 +85,45 @@ using std::string; #endif +#if APT_PKG_ABI >= 413 // 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 // 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 class pkgVersioningSystem; class pkgCache /*{{{*/ @@ -109,6 +138,7 @@ class pkgCache /*{{{*/ struct Description; struct Provides; struct Dependency; + struct StringItem; struct VerFile; struct DescFile; @@ -185,6 +215,7 @@ class pkgCache /*{{{*/ Description *DescP; Provides *ProvideP; Dependency *DepP; + APT_DEPRECATED StringItem *StringItemP; char *StrP; virtual bool ReMap(bool const &Errorchecks = true); @@ -288,12 +319,17 @@ 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 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 */ @@ -319,12 +355,26 @@ 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; - map_pointer_t * PkgHashTable() const { return (map_pointer_t*) (this + 1); } - map_pointer_t * GrpHashTable() const { return PkgHashTable() + HashTableSize; } + unsigned int 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 */ - unsigned long long CacheFileSize; + should_be_uint64_small_t CacheFileSize; bool CheckSizes(Header &Against) const APT_PURE; Header(); @@ -350,7 +400,7 @@ struct pkgCache::Group /** \brief Link to the next Group */ map_pointer_t Next; // Group /** \brief unique sequel ID */ - map_id_t ID; + should_be_map_id_t ID; }; /*}}}*/ @@ -387,12 +437,18 @@ 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 // Linked list /** \brief Link to the next package in the same bucket */ - map_pointer_t Next; // Package + map_pointer_t NextPackage; // Package /** \brief List of all dependencies on this package */ map_pointer_t RevDepends; // Dependency /** \brief List of all "packages" this package provide */ @@ -416,7 +472,7 @@ 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. */ - map_id_t ID; + should_be_map_id_t ID; /** \brief some useful indicators of the package's state */ unsigned long Flags; }; @@ -464,7 +520,7 @@ struct pkgCache::PackageFile /** \brief Link to the next PackageFile in the Cache */ map_pointer_t NextFile; // PackageFile /** \brief unique sequel ID */ - map_fileid_t ID; + should_be_map_fileid_t ID; }; /*}}}*/ // VerFile structure /*{{{*/ @@ -479,7 +535,7 @@ struct pkgCache::VerFile /** \brief next step in the linked list */ map_pointer_t NextFile; // PkgVerFile /** \brief position in the package file */ - map_filesize_t Offset; // File offset + should_be_map_filesize_t Offset; // File offset /** @TODO document pkgCache::VerFile::Size */ map_filesize_t Size; }; @@ -493,7 +549,7 @@ struct pkgCache::DescFile /** \brief next step in the linked list */ map_pointer_t NextFile; // PkgVerFile /** \brief position in the file */ - map_filesize_t Offset; // File offset + should_be_map_filesize_t Offset; // File offset /** @TODO document pkgCache::DescFile::Size */ map_filesize_t Size; }; @@ -556,16 +612,16 @@ struct pkgCache::Version /** \brief archive size for this version For Debian this is the size of the .deb file. */ - uint64_t Size; // These are the .deb size + should_be_uint64_t Size; // These are the .deb size /** \brief uncompressed size for this version */ - uint64_t InstalledSize; + should_be_uint64_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 */ - map_id_t ID; + should_be_map_id_t ID; /** \brief parsed priority value */ unsigned char Priority; }; @@ -593,7 +649,7 @@ struct pkgCache::Description map_pointer_t ParentPkg; // Package /** \brief unique sequel ID */ - map_id_t ID; + should_be_map_id_t ID; }; /*}}}*/ // Dependency structure /*{{{*/ @@ -620,7 +676,7 @@ struct pkgCache::Dependency map_pointer_t ParentVer; // Version /** \brief unique sequel ID */ - map_id_t ID; + should_be_map_id_t ID; /** \brief Dependency type - Depends, Recommends, Conflicts, etc */ unsigned char Type; /** \brief comparison operator specified on the depends line @@ -656,6 +712,15 @@ struct pkgCache::Provides map_pointer_t NextPkgProv; // Provides }; /*}}}*/ +// UNUSED StringItem structure /*{{{*/ +struct APT_DEPRECATED pkgCache::StringItem +{ + /** \brief string this refers to */ + map_ptrloc String; // StringItem + /** \brief Next link in the chain */ + map_ptrloc NextItem; // StringItem +}; + /*}}}*/ inline char const * pkgCache::NativeArch() { return StrP + HeaderP->Architecture; } diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index a2c1c8760..ba454f057 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -74,7 +74,7 @@ pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) : *Cache.HeaderP = pkgCache::Header(); // make room for the hashtables for packages and groups - if (Map.RawAllocate(2 * (Cache.HeaderP->HashTableSize * sizeof(map_pointer_t))) == 0) + if (Map.RawAllocate(2 * (Cache.HeaderP->GetHashTableSize() * sizeof(map_pointer_t))) == 0) return; map_stringitem_t const idxVerSysName = WriteStringInMap(_system->VS->Label); @@ -96,10 +96,10 @@ pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) : map_stringitem_t const idxArchitectures = WriteStringInMap(list); if (unlikely(idxArchitectures == 0)) return; - Cache.HeaderP->Architectures = idxArchitectures; + Cache.HeaderP->SetArchitectures(idxArchitectures); } else - Cache.HeaderP->Architectures = idxArchitecture; + Cache.HeaderP->SetArchitectures(idxArchitecture); Cache.ReMap(); } @@ -616,7 +616,7 @@ bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator &Grp, const string &Name) // Insert it into the hash table unsigned long const Hash = Cache.Hash(Name); - map_pointer_t *insertAt = &Cache.HeaderP->GrpHashTable()[Hash]; + map_pointer_t *insertAt = &Cache.HeaderP->GrpHashTableP()[Hash]; while (*insertAt != 0 && strcasecmp(Name.c_str(), Cache.StrP + (Cache.GrpP + *insertAt)->Name) > 0) insertAt = &(Cache.GrpP + *insertAt)->Next; Grp->Next = *insertAt; @@ -652,18 +652,18 @@ bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name Grp->FirstPackage = Package; // Insert it into the hash table map_id_t const Hash = Cache.Hash(Name); - map_pointer_t *insertAt = &Cache.HeaderP->PkgHashTable()[Hash]; + map_pointer_t *insertAt = &Cache.HeaderP->PkgHashTableP()[Hash]; while (*insertAt != 0 && strcasecmp(Name.c_str(), Cache.StrP + (Cache.GrpP + (Cache.PkgP + *insertAt)->Group)->Name) > 0) - insertAt = &(Cache.PkgP + *insertAt)->Next; - Pkg->Next = *insertAt; + insertAt = &(Cache.PkgP + *insertAt)->NextPackage; + Pkg->NextPackage = *insertAt; *insertAt = Package; } else // Group the Packages together { // this package is the new last package pkgCache::PkgIterator LastPkg(Cache, Cache.PkgP + Grp->LastPackage); - Pkg->Next = LastPkg->Next; - LastPkg->Next = Package; + Pkg->NextPackage = LastPkg->NextPackage; + LastPkg->NextPackage = Package; } Grp->LastPackage = Package; -- cgit v1.2.3 From 0dc0b42d73ffd08bbdbe08b0678fbaae02364622 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 7 Nov 2014 21:26:49 +0100 Subject: revert useless abibreak in sourceslist.h No idea what the intension was here, but it seems like a leftover from a workover which happened to be done differently later. As it doesn't provide anything at the moment we just revert to the previous abi here. Git-Dch: Ignore --- apt-pkg/sourcelist.h | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/sourcelist.h b/apt-pkg/sourcelist.h index 35b786e1a..998357509 100644 --- a/apt-pkg/sourcelist.h +++ b/apt-pkg/sourcelist.h @@ -52,23 +52,15 @@ class pkgAcquire; class pkgIndexFile; class metaIndex; -class pkgSource -{ - protected: - - std::vector SrcList; - -}; - -class pkgSourceList : public pkgSource +class pkgSourceList { public: - + // List of supported source list types class Type { public: - + // Global list of Items supported static Type **GlobalList; static unsigned long GlobalListLen; @@ -91,14 +83,18 @@ class pkgSourceList : public pkgSource Type(); virtual ~Type() {}; }; - + typedef std::vector::const_iterator const_iterator; - - public: + + protected: + + std::vector SrcList; int ParseFileDeb822(std::string File); bool ParseFileOldStyle(std::string File); + public: + bool ReadMainList(); bool Read(std::string File); -- cgit v1.2.3 From bc4ccfeb6096fc6f9a74e2abff3abe31261b5df2 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 7 Nov 2014 21:52:31 +0100 Subject: restore ABI of pkgTagSection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have a d-pointer available here, so go ahead and use it which also helps in hidding some dirty details here. The "hard" part is keeping the abi for the inlined methods so that they don't break – at least not more than before as much of the point beside a speedup is support for more than 256 fields in a single section. --- apt-pkg/tagfile.cc | 105 ++++++++++++++++++++++++++++++++++++++--------------- apt-pkg/tagfile.h | 24 ++++++------ 2 files changed, 86 insertions(+), 43 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc index 3ee5c7076..590206f17 100644 --- a/apt-pkg/tagfile.cc +++ b/apt-pkg/tagfile.cc @@ -47,6 +47,23 @@ public: unsigned long long Size; }; +class pkgTagSectionPrivate +{ +public: + pkgTagSectionPrivate() + { + } + struct TagData { + unsigned int StartTag; + unsigned int EndTag; + unsigned int StartValue; + unsigned int NextInBucket; + + TagData(unsigned int const StartTag) : StartTag(StartTag), EndTag(0), StartValue(0), NextInBucket(0) {} + }; + std::vector Tags; +}; + static unsigned long AlphaHash(const char *Text, size_t Length) /*{{{*/ { /* This very simple hash function for the last 8 letters gives @@ -274,11 +291,18 @@ bool pkgTagFile::Jump(pkgTagSection &Tag,unsigned long long Offset) // pkgTagSection::pkgTagSection - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ +APT_IGNORE_DEPRECATED_PUSH pkgTagSection::pkgTagSection() : Section(0), d(NULL), Stop(0) { - memset(&LookupTable, 0, sizeof(LookupTable)); + 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 @@ -292,9 +316,9 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const R Section = Start; const char *End = Start + MaxLength; - if (Restart == false && Tags.empty() == false) + if (Restart == false && d->Tags.empty() == false) { - Stop = Section + Tags.back().StartTag; + Stop = Section + d->Tags.back().StartTag; if (End <= Stop) return false; Stop = (const char *)memchr(Stop,'\n',End - Stop); @@ -305,19 +329,23 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const R else { Stop = Section; - if (Tags.empty() == false) + if (d->Tags.empty() == false) { - memset(&LookupTable, 0, sizeof(LookupTable)); - Tags.clear(); + memset(&AlphaIndexes, 0, sizeof(AlphaIndexes)); + d->Tags.clear(); } - Tags.reserve(0x100); + d->Tags.reserve(0x100); } - size_t TagCount = Tags.size(); +#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; - TagData lastTagData(0); + pkgTagSectionPrivate::TagData lastTagData(0); lastTagData.EndTag = 0; unsigned long lastTagHash = 0; while (Stop < End) @@ -335,14 +363,20 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const R // store the last found tag if (lastTagData.EndTag != 0) { - if (LookupTable[lastTagHash] != 0) - lastTagData.NextInBucket = LookupTable[lastTagHash]; - LookupTable[lastTagHash] = TagCount; - Tags.push_back(lastTagData); + if (AlphaIndexes[lastTagHash] != 0) + 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); } - ++TagCount; - lastTagData = TagData(Stop - Section); + APT_IGNORE_DEPRECATED(++TagCount;) + lastTagData = pkgTagSectionPrivate::TagData(Stop - Section); // find the colon separating tag and value char const * Colon = (char const *) memchr(Stop, ':', End - Stop); if (Colon == NULL) @@ -377,14 +411,20 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const R { if (lastTagData.EndTag != 0) { - if (LookupTable[lastTagHash] != 0) - lastTagData.NextInBucket = LookupTable[lastTagHash]; - LookupTable[lastTagHash] = TagCount; - Tags.push_back(lastTagData); + 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); } - TagData const td(Stop - Section); - Tags.push_back(td); + 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; } @@ -430,16 +470,16 @@ bool pkgTagSection::Exists(const char* const Tag) bool pkgTagSection::Find(const char *Tag,unsigned int &Pos) const { size_t const Length = strlen(Tag); - unsigned int Bucket = LookupTable[AlphaHash(Tag, Length)]; + unsigned int Bucket = AlphaIndexes[AlphaHash(Tag, Length)]; if (Bucket == 0) return false; - for (; Bucket != 0; Bucket = Tags[Bucket - 1].NextInBucket) + for (; Bucket != 0; Bucket = d->Tags[Bucket - 1].NextInBucket) { - if ((Tags[Bucket - 1].EndTag - Tags[Bucket - 1].StartTag) != Length) + if ((d->Tags[Bucket - 1].EndTag - d->Tags[Bucket - 1].StartTag) != Length) continue; - char const * const St = Section + Tags[Bucket - 1].StartTag; + char const * const St = Section + d->Tags[Bucket - 1].StartTag; if (strncasecmp(Tag,St,Length) != 0) continue; @@ -457,9 +497,9 @@ bool pkgTagSection::Find(const char *Tag,const char *&Start, if (Find(Tag, Pos) == false) return false; - Start = Section + Tags[Pos].StartValue; + Start = Section + d->Tags[Pos].StartValue; // Strip off the gunk from the end - End = Section + Tags[Pos + 1].StartTag; + End = Section + d->Tags[Pos + 1].StartTag; if (unlikely(Start > End)) return _error->Error("Internal parsing error"); @@ -571,11 +611,16 @@ bool pkgTagSection::FindFlag(unsigned long &Flags, unsigned long Flag, return true; } /*}}}*/ +void pkgTagSection::Get(const char *&Start,const char *&Stop,unsigned int I) const +{ + Start = Section + d->Tags[I].StartTag; + Stop = Section + d->Tags[I+1].StartTag; +} APT_PURE unsigned int pkgTagSection::Count() const { /*{{{*/ - if (Tags.empty() == true) + if (d->Tags.empty() == true) return 0; // the last element is just marking the end and isn't a real one - return Tags.size() - 1; + return d->Tags.size() - 1; } /*}}}*/ // TFRewrite - Rewrite a control record /*{{{*/ @@ -768,4 +813,4 @@ bool TFRewrite(FILE *Output,pkgTagSection const &Tags,const char *Order[], } /*}}}*/ -pkgTagSection::~pkgTagSection() {} +pkgTagSection::~pkgTagSection() { delete d; } diff --git a/apt-pkg/tagfile.h b/apt-pkg/tagfile.h index ac6d42089..d09e7046c 100644 --- a/apt-pkg/tagfile.h +++ b/apt-pkg/tagfile.h @@ -33,23 +33,22 @@ #endif class FileFd; +class pkgTagSectionPrivate; class pkgTagSection { const char *Section; - struct TagData { - unsigned int StartTag; - unsigned int EndTag; - unsigned int StartValue; - unsigned int NextInBucket; - - TagData(unsigned int const StartTag) : StartTag(StartTag), EndTag(0), StartValue(0), NextInBucket(0) {} - }; - std::vector Tags; - unsigned int LookupTable[0x100]; + // 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) - void *d; + pkgTagSectionPrivate *d; protected: const char *Stop; @@ -109,8 +108,7 @@ class pkgTagSection bool Exists(const char* const Tag); #endif - inline void Get(const char *&Start,const char *&Stop,unsigned int I) const - {Start = Section + Tags[I].StartTag; Stop = Section + Tags[I+1].StartTag;} + void Get(const char *&Start,const char *&Stop,unsigned int I) const; inline void GetSection(const char *&Start,const char *&Stop) const { -- cgit v1.2.3 From 20801f613690b330c79b4f7a30dc3ff52b722468 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 8 Nov 2014 14:23:18 +0100 Subject: fix variable naming typo used in debug output Git-Dch: Ignore --- apt-pkg/acquire-worker.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-worker.cc b/apt-pkg/acquire-worker.cc index 724bdfd49..f4d1ad412 100644 --- a/apt-pkg/acquire-worker.cc +++ b/apt-pkg/acquire-worker.cc @@ -346,28 +346,28 @@ bool pkgAcquire::Worker::RunMessages() Owner->DestFile.c_str(), LookupTag(Message,"Size","0").c_str(),TotalSize); // see if there is a hash to verify - HashStringList RecivedHashes; + HashStringList ReceivedHashes; HashStringList expectedHashes = Owner->HashSums(); for (HashStringList::const_iterator hs = expectedHashes.begin(); hs != expectedHashes.end(); ++hs) { std::string const tagname = hs->HashType() + "-Hash"; std::string const hashsum = LookupTag(Message, tagname.c_str()); if (hashsum.empty() == false) - RecivedHashes.push_back(HashString(hs->HashType(), hashsum)); + ReceivedHashes.push_back(HashString(hs->HashType(), hashsum)); } if(_config->FindB("Debug::pkgAcquire::Auth", false) == true) { std::clog << "201 URI Done: " << Owner->DescURI() << endl - << "RecivedHash:" << endl; - for (HashStringList::const_iterator hs = RecivedHashes.begin(); hs != RecivedHashes.end(); ++hs) + << "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; } - Owner->Done(Message, ServerSize, RecivedHashes, Config); + Owner->Done(Message, ServerSize, ReceivedHashes, Config); ItemDone(); // Log that we are done -- cgit v1.2.3 From ad7e0941b376d792911f240377094a2e78ca8756 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 8 Nov 2014 18:14:46 +0100 Subject: streamline display of --help in all tools By convention, if I run a tool with --help or --version I expect it to exit successfully with the usage, while if I do call it wrong (like without any parameters) I expect the usage message shown with a non-zero exit. --- apt-pkg/contrib/cmndline.cc | 3 +++ apt-pkg/contrib/cmndline.h | 1 + 2 files changed, 4 insertions(+) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/cmndline.cc b/apt-pkg/contrib/cmndline.cc index 93c1f4664..ff8b09ebc 100644 --- a/apt-pkg/contrib/cmndline.cc +++ b/apt-pkg/contrib/cmndline.cc @@ -33,6 +33,9 @@ using namespace std; CommandLine::CommandLine(Args *AList,Configuration *Conf) : ArgList(AList), Conf(Conf), FileList(0) { +} +CommandLine::CommandLine() : ArgList(NULL), Conf(NULL), FileList(0) +{ } /*}}}*/ // CommandLine::~CommandLine - Destructor /*{{{*/ diff --git a/apt-pkg/contrib/cmndline.h b/apt-pkg/contrib/cmndline.h index 143df58b2..58cbaa8c3 100644 --- a/apt-pkg/contrib/cmndline.h +++ b/apt-pkg/contrib/cmndline.h @@ -91,6 +91,7 @@ class CommandLine static CommandLine::Args MakeArgs(char ShortOpt, char const *LongOpt, char const *ConfName, unsigned long Flags) APT_CONST; + CommandLine(); CommandLine(Args *AList,Configuration *Conf); ~CommandLine(); }; -- cgit v1.2.3 From 7e04a6bf23d857db60afd2ec3d0f4a8271b1c597 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 9 Nov 2014 19:04:54 +0100 Subject: use pkgAcquire::GetLock instead of own code Do the same with less code in apt-get. This especially ensures that the lock file (and the parent directories) exist before we are trying to lock. It also means that clean now creates the directories if they are missing so we returned to a proper clean state now. Git-Dch: Ignore --- apt-pkg/acquire.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc index 2c89c2dea..07c4646f5 100644 --- a/apt-pkg/acquire.cc +++ b/apt-pkg/acquire.cc @@ -152,6 +152,8 @@ bool pkgAcquire::GetLock(std::string const &Lock) return true; // Lock the directory this acquire object will work in + if (LockFD != -1) + close(LockFD); LockFD = ::GetLock(flCombine(Lock, "lock")); if (LockFD == -1) return _error->Error(_("Unable to lock directory %s"), Lock.c_str()); -- cgit v1.2.3 From 3f439e2b7126fb82952cd7bc12b8d6cb01352219 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 18 Aug 2013 23:17:05 +0200 Subject: add a simple container for HashStrings APT supports more than just one HashString and even allows to enforce the usage of a specific hash. This class is intended to help with storage and passing around of the HashStrings. The cherry-pick here the un-const-ification of HashType() compared to f4c3850ea335545e297504941dc8c7a8f1c83358. The point of this commit is adding infrastructure for the next one. All by itself, it just adds new symbols. Git-Dch: Ignore --- apt-pkg/contrib/hashes.cc | 118 ++++++++++++++++++++++++++++++++++++++++------ apt-pkg/contrib/hashes.h | 84 ++++++++++++++++++++++++++++++++- 2 files changed, 187 insertions(+), 15 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/hashes.cc b/apt-pkg/contrib/hashes.cc index 15f83615d..bb11a3fca 100644 --- a/apt-pkg/contrib/hashes.cc +++ b/apt-pkg/contrib/hashes.cc @@ -27,7 +27,7 @@ #include /*}}}*/ -const char* HashString::_SupportedHashes[] = +const char * HashString::_SupportedHashes[] = { "SHA512", "SHA256", "SHA1", "MD5Sum", NULL }; @@ -42,11 +42,16 @@ HashString::HashString(std::string Type, std::string Hash) : Type(Type), Hash(Ha HashString::HashString(std::string StringedHash) /*{{{*/ { - // legacy: md5sum without "MD5Sum:" prefix - if (StringedHash.find(":") == std::string::npos && StringedHash.size() == 32) + if (StringedHash.find(":") == std::string::npos) { - Type = "MD5Sum"; - Hash = StringedHash; + // legacy: md5sum without "MD5Sum:" prefix + if (StringedHash.size() == 32) + { + Type = "MD5Sum"; + Hash = StringedHash; + } + if(_config->FindB("Debug::Hashes",false) == true) + std::clog << "HashString(string): invalid StringedHash " << StringedHash << std::endl; return; } std::string::size_type pos = StringedHash.find(":"); @@ -82,25 +87,25 @@ std::string HashString::GetHashForFile(std::string filename) const /*{{{*/ std::string fileHash; FileFd Fd(filename, FileFd::ReadOnly); - if(Type == "MD5Sum") + if(strcasecmp(Type.c_str(), "MD5Sum") == 0) { MD5Summation MD5; MD5.AddFD(Fd); fileHash = (std::string)MD5.Result(); } - else if (Type == "SHA1") + else if (strcasecmp(Type.c_str(), "SHA1") == 0) { SHA1Summation SHA1; SHA1.AddFD(Fd); fileHash = (std::string)SHA1.Result(); } - else if (Type == "SHA256") + else if (strcasecmp(Type.c_str(), "SHA256") == 0) { SHA256Summation SHA256; SHA256.AddFD(Fd); fileHash = (std::string)SHA256.Result(); } - else if (Type == "SHA512") + else if (strcasecmp(Type.c_str(), "SHA512") == 0) { SHA512Summation SHA512; SHA512.AddFD(Fd); @@ -111,20 +116,105 @@ std::string HashString::GetHashForFile(std::string filename) const /*{{{*/ return fileHash; } /*}}}*/ -const char** HashString::SupportedHashes() +const char** HashString::SupportedHashes() /*{{{*/ { return _SupportedHashes; } - -APT_PURE bool HashString::empty() const + /*}}}*/ +APT_PURE bool HashString::empty() const /*{{{*/ { return (Type.empty() || Hash.empty()); } + /*}}}*/ +std::string HashString::toStr() const /*{{{*/ +{ + return Type + ":" + Hash; +} + /*}}}*/ +APT_PURE bool HashString::operator==(HashString const &other) const /*{{{*/ +{ + return (strcasecmp(Type.c_str(), other.Type.c_str()) == 0 && Hash == other.Hash); +} +APT_PURE bool HashString::operator!=(HashString const &other) const +{ + return !(*this == other); +} + /*}}}*/ + +HashString const * HashStringList::find(char const * const type) const /*{{{*/ +{ + if (type == NULL || type[0] == '\0') + { + std::string forcedType = _config->Find("Acquire::ForceHash", ""); + if (forcedType.empty() == false) + return find(forcedType.c_str()); + for (char const * const * t = HashString::SupportedHashes(); *t != NULL; ++t) + for (std::vector::const_iterator hs = list.begin(); hs != list.end(); ++hs) + if (strcasecmp(hs->HashType().c_str(), *t) == 0) + return &*hs; + return NULL; + } + for (std::vector::const_iterator hs = list.begin(); hs != list.end(); ++hs) + if (strcasecmp(hs->HashType().c_str(), type) == 0) + return &*hs; + return NULL; +} + /*}}}*/ +bool HashStringList::supported(char const * const type) /*{{{*/ +{ + for (char const * const * t = HashString::SupportedHashes(); *t != NULL; ++t) + if (strcasecmp(*t, type) == 0) + return true; + return false; +} + /*}}}*/ +bool HashStringList::push_back(const HashString &hashString) /*{{{*/ +{ + if (hashString.HashType().empty() == true || + hashString.HashValue().empty() == true || + supported(hashString.HashType().c_str()) == false) + return false; + + // ensure that each type is added only once + HashString const * const hs = find(hashString.HashType().c_str()); + if (hs != NULL) + return *hs == hashString; -std::string HashString::toStr() const + list.push_back(hashString); + return true; +} + /*}}}*/ +bool HashStringList::VerifyFile(std::string filename) const /*{{{*/ { - return Type + std::string(":") + Hash; + if (list.empty() == true) + return false; + HashString const * const hs = find(NULL); + if (hs == NULL || hs->VerifyFile(filename) == false) + return false; + return true; } + /*}}}*/ +bool HashStringList::operator==(HashStringList const &other) const /*{{{*/ +{ + short matches = 0; + for (const_iterator hs = begin(); hs != end(); ++hs) + { + HashString const * const ohs = other.find(hs->HashType()); + if (ohs == NULL) + continue; + if (*hs != *ohs) + return false; + ++matches; + } + if (matches == 0) + return false; + return true; +} +bool HashStringList::operator!=(HashStringList const &other) const +{ + return !(*this == other); +} + /*}}}*/ // Hashes::AddFD - Add the contents of the FD /*{{{*/ // --------------------------------------------------------------------- diff --git a/apt-pkg/contrib/hashes.h b/apt-pkg/contrib/hashes.h index 7a62f8a8f..5a4213868 100644 --- a/apt-pkg/contrib/hashes.h +++ b/apt-pkg/contrib/hashes.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -41,7 +42,7 @@ class HashString protected: std::string Type; std::string Hash; - static const char* _SupportedHashes[10]; + static const char * _SupportedHashes[10]; // internal helper std::string GetHashForFile(std::string filename) const; @@ -53,6 +54,8 @@ class HashString // get hash type used std::string HashType() { return Type; }; + std::string HashType() const { return Type; }; + std::string HashValue() const { return Hash; }; // verify the given filename against the currently loaded hash bool VerifyFile(std::string filename) const; @@ -64,11 +67,90 @@ class HashString // helper std::string toStr() const; // convert to str as "type:hash" bool empty() const; + bool operator==(HashString const &other) const; + bool operator!=(HashString const &other) const; // return the list of hashes we support static APT_CONST const char** SupportedHashes(); }; +class HashStringList +{ + public: + /** find best hash if no specific one is requested + * + * @param type of the checksum to return, can be \b NULL + * @return If type is \b NULL (or the empty string) it will + * return the 'best' hash; otherwise the hash which was + * specifically requested. If no hash is found \b NULL will be returned. + */ + HashString const * find(char const * const type) const; + HashString const * find(std::string const &type) const { return find(type.c_str()); } + /** check if the given hash type is supported + * + * @param type to check + * @return true if supported, otherwise false + */ + static APT_PURE bool supported(char const * const type); + /** add the given #HashString to the list + * + * @param hashString to add + * @return true if the hash is added because it is supported and + * not already a different hash of the same type included, otherwise false + */ + bool push_back(const HashString &hashString); + /** @return size of the list of HashStrings */ + size_t size() const { return list.size(); } + + /** take the 'best' hash and verify file with it + * + * @param filename to verify + * @return true if the file matches the hashsum, otherwise false + */ + bool VerifyFile(std::string filename) const; + + /** is the list empty ? + * + * @return \b true if the list is empty, otherwise \b false + */ + bool empty() const { return list.empty(); } + + typedef std::vector::const_iterator const_iterator; + + /** iterator to the first element */ + const_iterator begin() const { return list.begin(); } + + /** iterator to the end element */ + const_iterator end() const { return list.end(); } + + /** start fresh with a clear list */ + void clear() { list.clear(); } + + /** compare two HashStringList for similarity. + * + * Two lists are similar if at least one hashtype is in both lists + * and the hashsum matches. All hashes are checked, if one doesn't + * match false is returned regardless of how many matched before. + */ + bool operator==(HashStringList const &other) const; + bool operator!=(HashStringList const &other) const; + + HashStringList() {} + + // simplifying API-compatibility constructors + HashStringList(std::string const &hash) { + if (hash.empty() == false) + list.push_back(HashString(hash)); + } + HashStringList(char const * const hash) { + if (hash != NULL && hash[0] != '\0') + list.push_back(HashString(hash)); + } + + private: + std::vector list; +}; + class Hashes { public: -- cgit v1.2.3 From 3a2b39ee602dd5a98b8fdaee2f1c8e0b13a276e2 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 18 Aug 2013 23:27:24 +0200 Subject: use 'best' hash for source authentication Collect all hashes we can get from the source record and put them into a HashStringList so that 'apt-get source' can use it instead of using always the MD5sum. We therefore also deprecate the MD5 struct member in favor of the list. While at it, the parsing of the Files is enhanced so that records which miss "Files" (aka MD5 checksums) are still searched for other checksums as they include just as much data, just not with a nice and catchy name. This is a cherry-pick of 1262d35 with some dirty tricks to preserve ABI. LP: 1098738 --- apt-pkg/deb/debsrcrecords.cc | 162 +++++++++++++++++++++++++++++++------------ apt-pkg/deb/debsrcrecords.h | 1 + apt-pkg/srcrecords.cc | 31 ++++++++- apt-pkg/srcrecords.h | 21 +++++- 4 files changed, 167 insertions(+), 48 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/debsrcrecords.cc b/apt-pkg/deb/debsrcrecords.cc index a444cbe4d..49a348dd4 100644 --- a/apt-pkg/deb/debsrcrecords.cc +++ b/apt-pkg/deb/debsrcrecords.cc @@ -118,13 +118,32 @@ bool debSrcRecordParser::BuildDepends(std::vector &List) +bool debSrcRecordParser::Files(std::vector &F) { - List.erase(List.begin(),List.end()); - - string Files = Sect.FindS("Files"); - if (Files.empty() == true) + std::vector F2; + if (Files2(F2) == false) return false; + for (std::vector::const_iterator f2 = F2.begin(); f2 != F2.end(); ++f2) + { + pkgSrcRecords::File2 f; +#if __GNUC__ >= 4 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + f.MD5Hash = f2->MD5Hash; + f.Size = f2->Size; +#if __GNUC__ >= 4 + #pragma GCC diagnostic pop +#endif + f.Path = f2->Path; + f.Type = f2->Type; + F.push_back(f); + } + return true; +} +bool debSrcRecordParser::Files2(std::vector &List) +{ + List.clear(); // Stash the / terminated directory prefix string Base = Sect.FindS("Directory"); @@ -133,51 +152,106 @@ bool debSrcRecordParser::Files(std::vector &List) std::vector const compExts = APT::Configuration::getCompressorExtensions(); - // Iterate over the entire list grabbing each triplet - const char *C = Files.c_str(); - while (*C != 0) - { - pkgSrcRecords::File F; - string Size; - - // Parse each of the elements - if (ParseQuoteWord(C,F.MD5Hash) == false || - ParseQuoteWord(C,Size) == false || - ParseQuoteWord(C,F.Path) == false) - return _error->Error("Error parsing file record"); - - // Parse the size and append the directory - F.Size = atoi(Size.c_str()); - F.Path = Base + F.Path; - - // Try to guess what sort of file it is we are getting. - string::size_type Pos = F.Path.length()-1; - while (1) + for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type) + { + // derive field from checksum type + std::string checksumField("Checksums-"); + if (strcmp(*type, "MD5Sum") == 0) + checksumField = "Files"; // historic name for MD5 checksums + else + checksumField.append(*type); + + string const Files = Sect.FindS(checksumField.c_str()); + if (Files.empty() == true) + continue; + + // Iterate over the entire list grabbing each triplet + const char *C = Files.c_str(); + while (*C != 0) { - string::size_type Tmp = F.Path.rfind('.',Pos); - if (Tmp == string::npos) - break; - if (F.Type == "tar") { - // source v3 has extension 'debian.tar.*' instead of 'diff.*' - if (string(F.Path, Tmp+1, Pos-Tmp) == "debian") - F.Type = "diff"; - break; - } - F.Type = string(F.Path,Tmp+1,Pos-Tmp); - - if (std::find(compExts.begin(), compExts.end(), std::string(".").append(F.Type)) != compExts.end() || - F.Type == "tar") + string hash, size, path; + + // Parse each of the elements + if (ParseQuoteWord(C, hash) == false || + ParseQuoteWord(C, size) == false || + ParseQuoteWord(C, path) == false) + return _error->Error("Error parsing file record in %s of source package %s", checksumField.c_str(), Package().c_str()); + + HashString const hashString(*type, hash); + if (Base.empty() == false) + path = Base + path; + + // look if we have a record for this file already + std::vector::iterator file = List.begin(); + for (; file != List.end(); ++file) + if (file->Path == path) + break; + + // we have it already, store the new hash and be done + if (file != List.end()) { - Pos = Tmp-1; +#if __GNUC__ >= 4 + // set for compatibility only, so warn users not us + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + if (checksumField == "Files") + file->MD5Hash = hash; +#if __GNUC__ >= 4 + #pragma GCC diagnostic pop +#endif + // an error here indicates that we have two different hashes for the same file + if (file->Hashes.push_back(hashString) == false) + return _error->Error("Error parsing checksum in %s of source package %s", checksumField.c_str(), Package().c_str()); continue; } - - break; + + // we haven't seen this file yet + pkgSrcRecords::File2 F; + F.Path = path; + F.FileSize = strtoull(size.c_str(), NULL, 10); + F.Hashes.push_back(hashString); + +#if __GNUC__ >= 4 + // set for compatibility only, so warn users not us + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + F.Size = F.FileSize; + if (checksumField == "Files") + F.MD5Hash = hash; +#if __GNUC__ >= 4 + #pragma GCC diagnostic pop +#endif + + // Try to guess what sort of file it is we are getting. + string::size_type Pos = F.Path.length()-1; + while (1) + { + string::size_type Tmp = F.Path.rfind('.',Pos); + if (Tmp == string::npos) + break; + if (F.Type == "tar") { + // source v3 has extension 'debian.tar.*' instead of 'diff.*' + if (string(F.Path, Tmp+1, Pos-Tmp) == "debian") + F.Type = "diff"; + break; + } + F.Type = string(F.Path,Tmp+1,Pos-Tmp); + + if (std::find(compExts.begin(), compExts.end(), std::string(".").append(F.Type)) != compExts.end() || + F.Type == "tar") + { + Pos = Tmp-1; + continue; + } + + break; + } + List.push_back(F); } - - List.push_back(F); } - + return true; } /*}}}*/ diff --git a/apt-pkg/deb/debsrcrecords.h b/apt-pkg/deb/debsrcrecords.h index b65d1480b..2a3fc86c9 100644 --- a/apt-pkg/deb/debsrcrecords.h +++ b/apt-pkg/deb/debsrcrecords.h @@ -53,6 +53,7 @@ class debSrcRecordParser : public pkgSrcRecords::Parser return std::string(Start,Stop); }; virtual bool Files(std::vector &F); + bool Files2(std::vector &F); debSrcRecordParser(std::string const &File,pkgIndexFile const *Index) : Parser(Index), Fd(File,FileFd::ReadOnly, FileFd::Extension), Tags(&Fd,102400), diff --git a/apt-pkg/srcrecords.cc b/apt-pkg/srcrecords.cc index 81b1c545d..3175ee75f 100644 --- a/apt-pkg/srcrecords.cc +++ b/apt-pkg/srcrecords.cc @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -147,5 +148,33 @@ const char *pkgSrcRecords::Parser::BuildDepType(unsigned char const &Type) return fields[Type]; } /*}}}*/ +bool pkgSrcRecords::Parser::Files2(std::vector &F2)/*{{{*/ +{ + debSrcRecordParser * const deb = dynamic_cast(this); + if (deb != NULL) + return deb->Files2(F2); - + std::vector F; + if (Files(F) == false) + return false; + for (std::vector::const_iterator f = F.begin(); f != F.end(); ++f) + { + pkgSrcRecords::File2 f2; +#if __GNUC__ >= 4 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + f2.MD5Hash = f->MD5Hash; + f2.Size = f->Size; + f2.Hashes.push_back(HashString("MD5Sum", f->MD5Hash)); + f2.FileSize = f->Size; +#if __GNUC__ >= 4 + #pragma GCC diagnostic pop +#endif + f2.Path = f->Path; + f2.Type = f->Type; + F2.push_back(f2); + } + return true; +} + /*}}}*/ diff --git a/apt-pkg/srcrecords.h b/apt-pkg/srcrecords.h index e000e176a..dde22bd65 100644 --- a/apt-pkg/srcrecords.h +++ b/apt-pkg/srcrecords.h @@ -14,6 +14,7 @@ #define PKGLIB_SRCRECORDS_H #include +#include #include #include @@ -29,15 +30,28 @@ class pkgSrcRecords { public: +#if __GNUC__ >= 4 + // ensure that con- & de-structor don't trigger this warning + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif // Describes a single file struct File { - std::string MD5Hash; - unsigned long Size; + APT_DEPRECATED std::string MD5Hash; + APT_DEPRECATED unsigned long Size; std::string Path; std::string Type; }; - + struct File2 : public File + { + unsigned long long FileSize; + HashStringList Hashes; + }; +#if __GNUC__ >= 4 + #pragma GCC diagnostic pop +#endif + // Abstract parser for each source record class Parser { @@ -77,6 +91,7 @@ class pkgSrcRecords static const char *BuildDepType(unsigned char const &Type) APT_PURE; virtual bool Files(std::vector &F) = 0; + bool Files2(std::vector &F); Parser(const pkgIndexFile *Index) : iIndex(Index) {}; virtual ~Parser() {}; -- cgit v1.2.3 From 50ef3344c3afaaf9943142906b2f976a0337d264 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 13 Jun 2014 08:35:32 +0200 Subject: deprecate the Section member from package struct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A version belongs to a section and has hence a section member of its own. A package on the other hand can have multiple versions from different sections. This was "solved" by using the section which was parsed first as order of sources.list defines, but that is obviously a horribly unpredictable thing. Users are way better of with the Section() as returned by the version they are dealing with. It is likely the same for all versions of a package, but in the few cases it isn't, it is important (like packages moving from main/* to contrib/* or into oldlibs …). Backport of 7a66977 which actually instantly removes the member. --- apt-pkg/cacheiterators.h | 4 +++- apt-pkg/cacheset.h | 11 ++++++++++- apt-pkg/depcache.cc | 2 +- apt-pkg/pkgcache.cc | 5 ++++- 4 files changed, 18 insertions(+), 4 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h index 2fdf8404d..513f40f17 100644 --- a/apt-pkg/cacheiterators.h +++ b/apt-pkg/cacheiterators.h @@ -160,7 +160,9 @@ class pkgCache::PkgIterator: public Iterator { // Accessors inline const char *Name() const {return S->Name == 0?0:Owner->StrP + S->Name;} - inline const char *Section() const {return S->Section == 0?0:Owner->StrP + S->Section;} + // 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 {return S->Section == 0?0:Owner->StrP + S->Section;} 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;} diff --git a/apt-pkg/cacheset.h b/apt-pkg/cacheset.h index 16a3daa42..b7229bc04 100644 --- a/apt-pkg/cacheset.h +++ b/apt-pkg/cacheset.h @@ -118,7 +118,16 @@ public: 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 *Section() const {return getPkg().Section(); } + APT_DEPRECATED inline const char *Section() const { +#if __GNUC__ >= 4 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + return getPkg().Section(); +#if __GNUC__ >= 4 + #pragma GCC diagnostic pop +#endif + } inline bool Purge() const {return getPkg().Purge(); } inline const char *Arch() const {return getPkg().Arch(); } inline pkgCache::GrpIterator Group() const { return getPkg().Group(); } diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 42e31396b..16282df21 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -1226,7 +1226,7 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, continue; } // now check if we should consider it a automatic dependency or not - if(InstPkg->CurrentVer == 0 && Pkg->Section != 0 && ConfigValueInSubTree("APT::Never-MarkAuto-Sections", Pkg.Section())) + if(InstPkg->CurrentVer == 0 && InstVer->Section != 0 && ConfigValueInSubTree("APT::Never-MarkAuto-Sections", InstVer.Section())) { if(DebugAutoInstall == true) std::clog << OutputInDepth(Depth) << "Setting NOT as auto-installed (direct " diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index 58a63459f..d7c9656b9 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -524,7 +524,10 @@ operator<<(std::ostream& out, pkgCache::PkgIterator Pkg) out << " -> " << candidate; if ( newest != "none" && candidate != newest) out << " | " << newest; - out << " > ( " << string(Pkg.Section()==0?"none":Pkg.Section()) << " )"; + if (Pkg->VersionList == 0) + out << " > ( none )"; + else + out << " > ( " << string(Pkg.VersionList().Section()==0?"unknown":Pkg.VersionList().Section()) << " )"; return out; } /*}}}*/ -- cgit v1.2.3 From c505fa33a6441b451971ce6c636cf2ca4dacdc1d Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 28 Sep 2014 01:25:21 +0200 Subject: allow options between command and -- on commandline This used to work before we implemented a stricter commandline parser and e.g. the dd-schroot-cmd command constructs commandlines like this. Reported-By: Helmut Grohne --- apt-pkg/contrib/cmndline.cc | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/cmndline.cc b/apt-pkg/contrib/cmndline.cc index 3799c822d..93c1f4664 100644 --- a/apt-pkg/contrib/cmndline.cc +++ b/apt-pkg/contrib/cmndline.cc @@ -47,23 +47,26 @@ CommandLine::~CommandLine() char const * CommandLine::GetCommand(Dispatch const * const Map, unsigned int const argc, char const * const * const argv) { - // if there is a -- on the line there must be the word we search for around it - // as -- marks the end of the options, just not sure if the command can be - // considered an option or not, so accept both + // if there is a -- on the line there must be the word we search for either + // before it (as -- marks the end of the options) or right after it (as we can't + // decide if the command is actually an option, given that in theory, you could + // have parameters named like commands) for (size_t i = 1; i < argc; ++i) { if (strcmp(argv[i], "--") != 0) continue; - ++i; - if (i < argc) + // check if command is before -- + for (size_t k = 1; k < i; ++k) for (size_t j = 0; Map[j].Match != NULL; ++j) - if (strcmp(argv[i], Map[j].Match) == 0) + if (strcmp(argv[k], Map[j].Match) == 0) return Map[j].Match; - i -= 2; - if (i != 0) + // see if the next token after -- is the command + ++i; + if (i < argc) for (size_t j = 0; Map[j].Match != NULL; ++j) if (strcmp(argv[i], Map[j].Match) == 0) return Map[j].Match; + // we found a --, but not a command return NULL; } // no --, so search for the first word matching a command -- cgit v1.2.3 From 1b671a9ba2e42e43f4cb1be86dc052823cf6961f Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 14 Nov 2014 17:52:39 +0100 Subject: create directory for extended_states if needed Unlikely perhaps, but there is no guarantee that the directory we want to drop the file into actually exists, so create it if we must. --- apt-pkg/depcache.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 1332f3ee2..25c945ebb 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -237,9 +237,11 @@ bool pkgDepCache::writeStateFile(OpProgress * /*prog*/, bool InstalledOnly) /*{{ FileFd StateFile; string const state = _config->FindFile("Dir::State::extended_states"); + if (CreateAPTDirectoryIfNeeded(_config->FindDir("Dir::State"), flNotFile(state)) == false) + return false; // if it does not exist, create a empty one - if(!RealFileExists(state)) + if(!RealFileExists(state)) { StateFile.Open(state, FileFd::WriteAtomic); StateFile.Close(); -- cgit v1.2.3 From 8fe964f148344b8a55252fe52b6292a4ab86ea98 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 14 Nov 2014 18:01:09 +0100 Subject: create our cache and lib directory always with mode 755 We autocreate for a while now the last two directories in /var/lib/apt/lists (similar for /var/cache/apt/archives) which is very nice for systems having any of those on tmpfs or other non-persistent storage. This also means though that this creation is effected by the default umask, so for people with aggressive umasks like 027 the directories will be created with 750, which means all non-root users are left out, which is usually exactly what we want then this umask is set, but the cache and lib directories contain public knowledge. There isn't any need to protect them from viewers and they render apt completely useless if not readable. --- apt-pkg/acquire.cc | 7 +++++-- apt-pkg/cdrom.cc | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc index 07c4646f5..0c815c005 100644 --- a/apt-pkg/acquire.cc +++ b/apt-pkg/acquire.cc @@ -92,8 +92,11 @@ void pkgAcquire::Initialize() static bool SetupAPTPartialDirectory(std::string const &grand, std::string const &parent) { std::string const partial = parent + "partial"; - if (CreateAPTDirectoryIfNeeded(grand, partial) == false && - CreateAPTDirectoryIfNeeded(parent, partial) == false) + mode_t const mode = umask(S_IWGRP | S_IWOTH); + bool const creation_fail = (CreateAPTDirectoryIfNeeded(grand, partial) == false && + CreateAPTDirectoryIfNeeded(parent, partial) == false); + umask(mode); + if (creation_fail == true) return false; std::string const SandboxUser = _config->Find("APT::Sandbox::User"); diff --git a/apt-pkg/cdrom.cc b/apt-pkg/cdrom.cc index b97f7b036..aaa7b82e0 100644 --- a/apt-pkg/cdrom.cc +++ b/apt-pkg/cdrom.cc @@ -822,8 +822,11 @@ bool pkgCdrom::Add(pkgCdromStatus *log) /*{{{*/ // check for existence and possibly create state directory for copying string const listDir = _config->FindDir("Dir::State::lists"); string const partialListDir = listDir + "partial/"; - if (CreateAPTDirectoryIfNeeded(_config->FindDir("Dir::State"), partialListDir) == false && - CreateAPTDirectoryIfNeeded(listDir, partialListDir) == false) + mode_t const mode = umask(S_IWGRP | S_IWOTH); + bool const creation_fail = (CreateAPTDirectoryIfNeeded(_config->FindDir("Dir::State"), partialListDir) == false && + CreateAPTDirectoryIfNeeded(listDir, partialListDir) == false); + umask(mode); + if (creation_fail == true) { UnmountCDROM(CDROM, NULL); return _error->Errno("cdrom", _("List directory %spartial is missing."), listDir.c_str()); -- cgit v1.2.3 From 0c78757010a17173bdc79b818133697e7dcbf6a4 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 17 Nov 2014 15:06:35 +0100 Subject: close leaking slave fd after setting up pty magic The fd moves out of scope here anyway, so we should close it properly instead of leaking it which will tickle down to dpkg maintainer scripts. Closes: 767774 --- apt-pkg/deb/dpkgpm.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 3f6039e0d..dd03eac2c 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1158,8 +1158,7 @@ void pkgDPkgPM::SetupSlavePtyMagic() int const slaveFd = open(d->slave, O_RDWR); if (slaveFd == -1) _error->FatalE("open", _("Can not write log (%s)"), _("Is /dev/pts mounted?")); - - if (ioctl(slaveFd, TIOCSCTTY, 0) < 0) + else if (ioctl(slaveFd, TIOCSCTTY, 0) < 0) _error->FatalE("ioctl", "Setting TIOCSCTTY for slave fd %d failed!", slaveFd); else { @@ -1170,6 +1169,9 @@ void pkgDPkgPM::SetupSlavePtyMagic() if (tcsetattr(0, TCSANOW, &d->tt) < 0) _error->FatalE("tcsetattr", "Setting in Setup via TCSANOW for slave fd %d failed!", slaveFd); } + + if (slaveFd != -1) + close(slaveFd); } void pkgDPkgPM::StopPtyMagic() { -- cgit v1.2.3 From 150bdc9ca5d656f9fba94d37c5f4f183b02bd746 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 18 Nov 2014 00:59:39 +0100 Subject: fix PTY interaction on linux and kfreebsd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We run dpkg on its own pty, so we can log its output and have our own output around it (like the progress bar), while also allowing debconf and configfile prompts to happen. In commit 223ae57d468fdcac451209a095047a07a5698212 we changed to constantly reopening the slave for kfreebsd. This has the sideeffect though that in some cases slave and master will lose their connection on linux, so that no output is passed along anymore. We fix this by having always an fd referencing the slave open (linux), but we don't use it (kfreebsd). Failing to get our PTY up and running has many (bad) consequences including (not limited to, nor all at ones or in any case) garbled ouput, no output, no logging, a (partial) mixture of the previous items, … This commit is therefore also reshuffling quiet a bit of the creation code to get especially the output part up and running on linux and the logging for kfreebsd. Note that the testcase tries to cover some cases, but this is an interactivity issue so only interactive usage can really be a good test. Closes: 765687 --- apt-pkg/deb/dpkgpm.cc | 99 ++++++++++++++++++++++++++++----------------------- 1 file changed, 55 insertions(+), 44 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index dd03eac2c..593875071 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -72,7 +72,8 @@ class pkgDPkgPMPrivate public: pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0), term_out(NULL), history_out(NULL), - progress(NULL), master(-1), slave(NULL) + progress(NULL), tt_is_valid(false), master(-1), + slave(NULL), protect_slave_from_dying(-1) { dpkgbuf[0] = '\0'; } @@ -90,8 +91,10 @@ public: // pty stuff struct termios tt; + bool tt_is_valid; int master; char * slave; + int protect_slave_from_dying; // signals sigset_t sigmask; @@ -1069,47 +1072,40 @@ void pkgDPkgPM::StartPtyMagic() } _error->PushToStack(); - // if tcgetattr for both stdin/stdout returns 0 (no error) - // we do the pty magic - if (tcgetattr(STDOUT_FILENO, &d->tt) == 0 && - tcgetattr(STDIN_FILENO, &d->tt) == 0) + + d->master = posix_openpt(O_RDWR | O_NOCTTY); + if (d->master == -1) + _error->Errno("posix_openpt", _("Can not write log (%s)"), _("Is /dev/pts mounted?")); + else if (unlockpt(d->master) == -1) + _error->Errno("unlockpt", "Unlocking the slave of master fd %d failed!", d->master); + else { - d->master = posix_openpt(O_RDWR | O_NOCTTY); - if (d->master == -1) - _error->Errno("posix_openpt", _("Can not write log (%s)"), _("Is /dev/pts mounted?")); - else if (unlockpt(d->master) == -1) - { - _error->Errno("unlockpt", "Unlocking the slave of master fd %d failed!", d->master); - close(d->master); - d->master = -1; - } + char const * const slave_name = ptsname(d->master); + if (slave_name == NULL) + _error->Errno("ptsname", "Getting name for slave of master fd %d failed!", d->master); else { - char const * const slave_name = ptsname(d->master); - if (slave_name == NULL) + d->slave = strdup(slave_name); + if (d->slave == NULL) + _error->Errno("strdup", "Copying name %s for slave of master fd %d failed!", slave_name, d->master); + else if (grantpt(d->master) == -1) + _error->Errno("grantpt", "Granting access to slave %s based on master fd %d failed!", slave_name, d->master); + else if (tcgetattr(STDIN_FILENO, &d->tt) == 0) { - _error->Errno("unlockpt", "Getting name for slave of master fd %d failed!", d->master); - close(d->master); - d->master = -1; - } - else - { - d->slave = strdup(slave_name); - if (d->slave == NULL) + d->tt_is_valid = true; + struct termios raw_tt; + // copy window size of stdout if its a 'good' terminal + if (tcgetattr(STDOUT_FILENO, &raw_tt) == 0) { - _error->Errno("strdup", "Copying name %s for slave of master fd %d failed!", slave_name, d->master); - close(d->master); - d->master = -1; + struct winsize win; + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) < 0) + _error->Errno("ioctl", "Getting TIOCGWINSZ from stdout failed!"); + if (ioctl(d->master, TIOCSWINSZ, &win) < 0) + _error->Errno("ioctl", "Setting TIOCSWINSZ for master fd %d failed!", d->master); } - struct winsize win; - if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) < 0) - _error->Errno("ioctl", "Getting TIOCGWINSZ from stdout failed!"); - if (ioctl(d->master, TIOCSWINSZ, &win) < 0) - _error->Errno("ioctl", "Setting TIOCSWINSZ for master fd %d failed!", d->master); if (tcsetattr(d->master, TCSANOW, &d->tt) == -1) _error->Errno("tcsetattr", "Setting in Start via TCSANOW for master fd %d failed!", d->master); - struct termios raw_tt; raw_tt = d->tt; cfmakeraw(&raw_tt); raw_tt.c_lflag &= ~ECHO; @@ -1121,18 +1117,22 @@ void pkgDPkgPM::StartPtyMagic() sigaddset(&d->sigmask, SIGTTOU); sigprocmask(SIG_BLOCK,&d->sigmask, &d->original_sigmask); if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw_tt) == -1) - _error->Errno("tcsetattr", "Setting in Start via TCSAFLUSH for stdout failed!"); + _error->Errno("tcsetattr", "Setting in Start via TCSAFLUSH for stdin failed!"); sigprocmask(SIG_SETMASK, &d->original_sigmask, NULL); + + } + if (d->slave != NULL) + { + /* on linux, closing (and later reopening) all references to the slave + makes the slave a death end, so we open it here to have one open all + the time. We could use this fd in SetupSlavePtyMagic() for linux, but + on kfreebsd we get an incorrect ("step like") output then while it has + no problem with closing all references… so to avoid platform specific + code here we combine both and be happy once more */ + d->protect_slave_from_dying = open(d->slave, O_RDWR | O_CLOEXEC); } } } - else - { - // complain only if stdout is either a terminal (but still failed) or is an invalid - // descriptor otherwise we would complain about redirection to e.g. /dev/null as well. - if (isatty(STDOUT_FILENO) == 1 || errno == EBADF) - _error->Errno("tcgetattr", _("Can not write log (%s)"), _("Is stdout a terminal?")); - } if (_error->PendingError() == true) { @@ -1141,17 +1141,23 @@ void pkgDPkgPM::StartPtyMagic() close(d->master); d->master = -1; } + if (d->slave != NULL) + { + free(d->slave); + d->slave = NULL; + } _error->DumpErrors(std::cerr); } _error->RevertToStack(); } void pkgDPkgPM::SetupSlavePtyMagic() { - if(d->master == -1) + if(d->master == -1 || d->slave == NULL) return; if (close(d->master) == -1) _error->FatalE("close", "Closing master %d in child failed!", d->master); + d->master = -1; if (setsid() == -1) _error->FatalE("setsid", "Starting a new session for child failed!"); @@ -1166,7 +1172,7 @@ void pkgDPkgPM::SetupSlavePtyMagic() if (dup2(slaveFd, i) == -1) _error->FatalE("dup2", "Dupping %d to %d in child failed!", slaveFd, i); - if (tcsetattr(0, TCSANOW, &d->tt) < 0) + if (d->tt_is_valid == true && tcsetattr(STDIN_FILENO, TCSANOW, &d->tt) < 0) _error->FatalE("tcsetattr", "Setting in Setup via TCSANOW for slave fd %d failed!", slaveFd); } @@ -1178,9 +1184,14 @@ void pkgDPkgPM::StopPtyMagic() if (d->slave != NULL) free(d->slave); d->slave = NULL; + if (d->protect_slave_from_dying != -1) + { + close(d->protect_slave_from_dying); + d->protect_slave_from_dying = -1; + } if(d->master >= 0) { - if (tcsetattr(0, TCSAFLUSH, &d->tt) == -1) + if (d->tt_is_valid == true && tcsetattr(STDIN_FILENO, TCSAFLUSH, &d->tt) == -1) _error->FatalE("tcsetattr", "Setting in Stop via TCSAFLUSH for stdin failed!"); close(d->master); d->master = -1; -- cgit v1.2.3 From 9fc0b435593839de47098212f0ae5f15b6263099 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 17 Nov 2014 15:06:35 +0100 Subject: close leaking slave fd after setting up pty magic The fd moves out of scope here anyway, so we should close it properly instead of leaking it which will tickle down to dpkg maintainer scripts. Closes: 767774 --- apt-pkg/deb/dpkgpm.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 7bbf18cba..e1f1ec680 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1160,8 +1160,7 @@ void pkgDPkgPM::SetupSlavePtyMagic() int const slaveFd = open(d->slave, O_RDWR); if (slaveFd == -1) _error->FatalE("open", _("Can not write log (%s)"), _("Is /dev/pts mounted?")); - - if (ioctl(slaveFd, TIOCSCTTY, 0) < 0) + else if (ioctl(slaveFd, TIOCSCTTY, 0) < 0) _error->FatalE("ioctl", "Setting TIOCSCTTY for slave fd %d failed!", slaveFd); else { @@ -1172,6 +1171,9 @@ void pkgDPkgPM::SetupSlavePtyMagic() if (tcsetattr(0, TCSANOW, &d->tt) < 0) _error->FatalE("tcsetattr", "Setting in Setup via TCSANOW for slave fd %d failed!", slaveFd); } + + if (slaveFd != -1) + close(slaveFd); } void pkgDPkgPM::StopPtyMagic() { -- cgit v1.2.3 From 299aea924ccef428219ed6f1a026c122678429e6 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 18 Nov 2014 00:59:39 +0100 Subject: fix PTY interaction on linux and kfreebsd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We run dpkg on its own pty, so we can log its output and have our own output around it (like the progress bar), while also allowing debconf and configfile prompts to happen. In commit 223ae57d468fdcac451209a095047a07a5698212 we changed to constantly reopening the slave for kfreebsd. This has the sideeffect though that in some cases slave and master will lose their connection on linux, so that no output is passed along anymore. We fix this by having always an fd referencing the slave open (linux), but we don't use it (kfreebsd). Failing to get our PTY up and running has many (bad) consequences including (not limited to, nor all at ones or in any case) garbled ouput, no output, no logging, a (partial) mixture of the previous items, … This commit is therefore also reshuffling quiet a bit of the creation code to get especially the output part up and running on linux and the logging for kfreebsd. Note that the testcase tries to cover some cases, but this is an interactivity issue so only interactive usage can really be a good test. Closes: 765687 --- apt-pkg/deb/dpkgpm.cc | 99 ++++++++++++++++++++++++++++----------------------- 1 file changed, 55 insertions(+), 44 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index e1f1ec680..e36a52c3e 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -72,7 +72,8 @@ class pkgDPkgPMPrivate public: pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0), term_out(NULL), history_out(NULL), - progress(NULL), master(-1), slave(NULL) + progress(NULL), tt_is_valid(false), master(-1), + slave(NULL), protect_slave_from_dying(-1) { dpkgbuf[0] = '\0'; } @@ -90,8 +91,10 @@ public: // pty stuff struct termios tt; + bool tt_is_valid; int master; char * slave; + int protect_slave_from_dying; // signals sigset_t sigmask; @@ -1071,47 +1074,40 @@ void pkgDPkgPM::StartPtyMagic() } _error->PushToStack(); - // if tcgetattr for both stdin/stdout returns 0 (no error) - // we do the pty magic - if (tcgetattr(STDOUT_FILENO, &d->tt) == 0 && - tcgetattr(STDIN_FILENO, &d->tt) == 0) + + d->master = posix_openpt(O_RDWR | O_NOCTTY); + if (d->master == -1) + _error->Errno("posix_openpt", _("Can not write log (%s)"), _("Is /dev/pts mounted?")); + else if (unlockpt(d->master) == -1) + _error->Errno("unlockpt", "Unlocking the slave of master fd %d failed!", d->master); + else { - d->master = posix_openpt(O_RDWR | O_NOCTTY); - if (d->master == -1) - _error->Errno("posix_openpt", _("Can not write log (%s)"), _("Is /dev/pts mounted?")); - else if (unlockpt(d->master) == -1) - { - _error->Errno("unlockpt", "Unlocking the slave of master fd %d failed!", d->master); - close(d->master); - d->master = -1; - } + char const * const slave_name = ptsname(d->master); + if (slave_name == NULL) + _error->Errno("ptsname", "Getting name for slave of master fd %d failed!", d->master); else { - char const * const slave_name = ptsname(d->master); - if (slave_name == NULL) + d->slave = strdup(slave_name); + if (d->slave == NULL) + _error->Errno("strdup", "Copying name %s for slave of master fd %d failed!", slave_name, d->master); + else if (grantpt(d->master) == -1) + _error->Errno("grantpt", "Granting access to slave %s based on master fd %d failed!", slave_name, d->master); + else if (tcgetattr(STDIN_FILENO, &d->tt) == 0) { - _error->Errno("unlockpt", "Getting name for slave of master fd %d failed!", d->master); - close(d->master); - d->master = -1; - } - else - { - d->slave = strdup(slave_name); - if (d->slave == NULL) + d->tt_is_valid = true; + struct termios raw_tt; + // copy window size of stdout if its a 'good' terminal + if (tcgetattr(STDOUT_FILENO, &raw_tt) == 0) { - _error->Errno("strdup", "Copying name %s for slave of master fd %d failed!", slave_name, d->master); - close(d->master); - d->master = -1; + struct winsize win; + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) < 0) + _error->Errno("ioctl", "Getting TIOCGWINSZ from stdout failed!"); + if (ioctl(d->master, TIOCSWINSZ, &win) < 0) + _error->Errno("ioctl", "Setting TIOCSWINSZ for master fd %d failed!", d->master); } - struct winsize win; - if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) < 0) - _error->Errno("ioctl", "Getting TIOCGWINSZ from stdout failed!"); - if (ioctl(d->master, TIOCSWINSZ, &win) < 0) - _error->Errno("ioctl", "Setting TIOCSWINSZ for master fd %d failed!", d->master); if (tcsetattr(d->master, TCSANOW, &d->tt) == -1) _error->Errno("tcsetattr", "Setting in Start via TCSANOW for master fd %d failed!", d->master); - struct termios raw_tt; raw_tt = d->tt; cfmakeraw(&raw_tt); raw_tt.c_lflag &= ~ECHO; @@ -1123,18 +1119,22 @@ void pkgDPkgPM::StartPtyMagic() sigaddset(&d->sigmask, SIGTTOU); sigprocmask(SIG_BLOCK,&d->sigmask, &d->original_sigmask); if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw_tt) == -1) - _error->Errno("tcsetattr", "Setting in Start via TCSAFLUSH for stdout failed!"); + _error->Errno("tcsetattr", "Setting in Start via TCSAFLUSH for stdin failed!"); sigprocmask(SIG_SETMASK, &d->original_sigmask, NULL); + + } + if (d->slave != NULL) + { + /* on linux, closing (and later reopening) all references to the slave + makes the slave a death end, so we open it here to have one open all + the time. We could use this fd in SetupSlavePtyMagic() for linux, but + on kfreebsd we get an incorrect ("step like") output then while it has + no problem with closing all references… so to avoid platform specific + code here we combine both and be happy once more */ + d->protect_slave_from_dying = open(d->slave, O_RDWR | O_CLOEXEC); } } } - else - { - // complain only if stdout is either a terminal (but still failed) or is an invalid - // descriptor otherwise we would complain about redirection to e.g. /dev/null as well. - if (isatty(STDOUT_FILENO) == 1 || errno == EBADF) - _error->Errno("tcgetattr", _("Can not write log (%s)"), _("Is stdout a terminal?")); - } if (_error->PendingError() == true) { @@ -1143,17 +1143,23 @@ void pkgDPkgPM::StartPtyMagic() close(d->master); d->master = -1; } + if (d->slave != NULL) + { + free(d->slave); + d->slave = NULL; + } _error->DumpErrors(std::cerr); } _error->RevertToStack(); } void pkgDPkgPM::SetupSlavePtyMagic() { - if(d->master == -1) + if(d->master == -1 || d->slave == NULL) return; if (close(d->master) == -1) _error->FatalE("close", "Closing master %d in child failed!", d->master); + d->master = -1; if (setsid() == -1) _error->FatalE("setsid", "Starting a new session for child failed!"); @@ -1168,7 +1174,7 @@ void pkgDPkgPM::SetupSlavePtyMagic() if (dup2(slaveFd, i) == -1) _error->FatalE("dup2", "Dupping %d to %d in child failed!", slaveFd, i); - if (tcsetattr(0, TCSANOW, &d->tt) < 0) + if (d->tt_is_valid == true && tcsetattr(STDIN_FILENO, TCSANOW, &d->tt) < 0) _error->FatalE("tcsetattr", "Setting in Setup via TCSANOW for slave fd %d failed!", slaveFd); } @@ -1180,9 +1186,14 @@ void pkgDPkgPM::StopPtyMagic() if (d->slave != NULL) free(d->slave); d->slave = NULL; + if (d->protect_slave_from_dying != -1) + { + close(d->protect_slave_from_dying); + d->protect_slave_from_dying = -1; + } if(d->master >= 0) { - if (tcsetattr(0, TCSAFLUSH, &d->tt) == -1) + if (d->tt_is_valid == true && tcsetattr(STDIN_FILENO, TCSAFLUSH, &d->tt) == -1) _error->FatalE("tcsetattr", "Setting in Stop via TCSAFLUSH for stdin failed!"); close(d->master); d->master = -1; -- cgit v1.2.3 From 4e6a7e260eb713318b1b5019a72073050242ac3c Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 25 Nov 2014 10:50:58 +0100 Subject: properly handle already reinstall pkgs in ordering The bugreport itself describes the case of the ordering code detecting a loop where none is present, but the testcase finds also cases in which there is actually a loop and we fail to realize it. --reinstall can be considered an interactive command through and it usually doesn't encounter such "hard" problems (= looping essentials), so this is less serious than it sounds at first. Closes: 770291 --- apt-pkg/packagemanager.cc | 46 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 10 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc index ba48c53cc..d137dc75a 100644 --- a/apt-pkg/packagemanager.cc +++ b/apt-pkg/packagemanager.cc @@ -400,7 +400,8 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) // Check if the current version of the package is available and will satisfy this dependency if (DepPkg.CurrentVer() == Ver && List->IsNow(DepPkg) == true && List->IsFlag(DepPkg,pkgOrderList::Removed) == false && - DepPkg.State() == PkgIterator::NeedsNothing) + DepPkg.State() == PkgIterator::NeedsNothing && + (Cache[DepPkg].iFlags & pkgDepCache::ReInstall) != pkgDepCache::ReInstall) { Bad = false; break; @@ -413,8 +414,13 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) if (PkgLoop == true) { if (Debug) - std::clog << OutputInDepth(Depth) << "Package " << Pkg << " loops in SmartConfigure" << std::endl; - Bad = false; + std::clog << OutputInDepth(Depth) << "Package " << Pkg << " loops in SmartConfigure"; + if (List->IsFlag(DepPkg,pkgOrderList::UnPacked)) + Bad = false; + else if (Debug) + std::clog << ", but it isn't unpacked yet"; + if (Debug) + std::clog << std::endl; } } @@ -426,7 +432,7 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) if (Bad == false) { if (Debug) - std::clog << OutputInDepth(Depth) << "Found ok dep " << D.TargetPkg() << std::endl; + std::clog << OutputInDepth(Depth) << "Found ok dep " << Start.TargetPkg() << std::endl; continue; } @@ -444,7 +450,8 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) // Check if the current version of the package is available and will satisfy this dependency if (DepPkg.CurrentVer() == Ver && List->IsNow(DepPkg) == true && List->IsFlag(DepPkg,pkgOrderList::Removed) == false && - DepPkg.State() == PkgIterator::NeedsNothing) + DepPkg.State() == PkgIterator::NeedsNothing && + (Cache[DepPkg].iFlags & pkgDepCache::ReInstall) != pkgDepCache::ReInstall) continue; // Check if the version that is going to be installed will satisfy the dependency @@ -454,8 +461,13 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) if (PkgLoop == true) { if (Debug) - std::clog << OutputInDepth(Depth) << "Package " << Pkg << " loops in SmartConfigure" << std::endl; - Bad = false; + std::clog << OutputInDepth(Depth) << "Package " << Pkg << " loops in SmartConfigure"; + if (List->IsFlag(DepPkg,pkgOrderList::UnPacked)) + Bad = false; + else if (Debug) + std::clog << ", but it isn't unpacked yet"; + if (Debug) + std::clog << std::endl; } else { @@ -722,7 +734,8 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c // See if the current version is ok if (Pkg.CurrentVer() == Ver && List->IsNow(Pkg) == true && - Pkg.State() == PkgIterator::NeedsNothing) + Pkg.State() == PkgIterator::NeedsNothing && + (Cache[Pkg].iFlags & pkgDepCache::ReInstall) != pkgDepCache::ReInstall) { Bad = false; if (Debug) @@ -744,8 +757,11 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c PkgIterator DepPkg = Ver.ParentPkg(); // Not the install version - if (Cache[DepPkg].InstallVer != *I || - (Cache[DepPkg].Keep() == true && DepPkg.State() == PkgIterator::NeedsNothing)) + if (Cache[DepPkg].InstallVer != *I) + continue; + + if (Cache[DepPkg].Keep() == true && DepPkg.State() == PkgIterator::NeedsNothing && + (Cache[DepPkg].iFlags & pkgDepCache::ReInstall) != pkgDepCache::ReInstall) continue; if (List->IsFlag(DepPkg,pkgOrderList::Configured)) @@ -757,6 +773,16 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c // check if it needs unpack or if if configure is enough if (List->IsFlag(DepPkg,pkgOrderList::UnPacked) == false) { + // two packages pre-depending on each other can't be handled sanely + if (List->IsFlag(DepPkg,pkgOrderList::Loop) && PkgLoop) + { + // this isn't an error as there is potential for something else to satisfy it + // (like a provides or an or-group member) + if (Debug) + clog << OutputInDepth(Depth) << "Unpack loop detected between " << DepPkg.FullName() << " and " << Pkg.FullName() << endl; + continue; + } + if (Debug) clog << OutputInDepth(Depth) << "Trying to SmartUnpack " << DepPkg.FullName() << endl; if (NonLoopingSmart(UNPACK_IMMEDIATE, Pkg, DepPkg, Depth, PkgLoop, &Bad, &Changed) == false) -- cgit v1.2.3 From 016bea8214e1826b289025f03890f70a5805db87 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 25 Nov 2014 12:10:15 +0100 Subject: correct architecture detection for 'rc' packages for purge We were already considering these cases, but the code was flawed, so that packages changing architectures are incorrectly handled and hence the wrong architecture is used to call dpkg with, so that dpkg says the package isn't installed (which it isn't for the requested architecture). Closes: 770898 --- apt-pkg/deb/dpkgpm.cc | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 593875071..3fbda0552 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -201,18 +201,10 @@ pkgCache::VerIterator FindNowVersion(const pkgCache::PkgIterator &Pkg) { pkgCache::VerIterator Ver; for (Ver = Pkg.VersionList(); Ver.end() == false; ++Ver) - { - pkgCache::VerFileIterator Vf = Ver.FileList(); - pkgCache::PkgFileIterator F = Vf.File(); - for (F = Vf.File(); F.end() == false; ++F) - { - if (F && F.Archive()) - { - if (strcmp(F.Archive(), "now")) - return 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) + return Ver; return Ver; } /*}}}*/ -- cgit v1.2.3 From ecb777ddb4d13bb7a18bbf2ebb8e2c810dcaeb72 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 18 Nov 2014 19:53:56 +0100 Subject: always run 'dpkg --configure -a' at the end of our dpkg callings dpkg checks now for dependencies before running triggers, so that packages can now end up in trigger states (especially those we are not touching at all with our calls) after apt is done running. The solution to this is trivial: Just tell dpkg to configure everything after we have (supposely) configured everything already. In the worst case this means dpkg will have to run a bunch of triggers, usually it will just do nothing though. The code to make this happen was already available, so we just flip a config option here to cause it to be run. This way we can keep pretending that triggers are an implementation detail of dpkg. --triggers-only would supposely work as well, but --configure is more robust in regards to future changes to dpkg and something we will hopefully make use of in future versions anyway (as it was planed at the time this and related options were implemented). Closes: 769609 --- apt-pkg/deb/dpkgpm.cc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 3fbda0552..79120f6f5 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1039,6 +1039,12 @@ void pkgDPkgPM::BuildPackagesProgressMap() PackagesTotal++; } } + /* one extra: We don't want the progress bar to reach 100%, especially not + if we call dpkg --configure --pending and process a bunch of triggers + while showing 100%. Also, spindown takes a while, so never reaching 100% + is way more correct than reaching 100% while still doing stuff even if + doing it this way is slightly bending the rules */ + ++PackagesTotal; } /*}}}*/ bool pkgDPkgPM::Go(int StatusFd) @@ -1266,9 +1272,8 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) // support subpressing of triggers processing for special // cases like d-i that runs the triggers handling manually - bool const SmartConf = (_config->Find("PackageManager::Configure", "all") != "all"); bool const TriggersPending = _config->FindB("DPkg::TriggersPending", false); - if (_config->FindB("DPkg::ConfigurePending", SmartConf) == true) + if (_config->FindB("DPkg::ConfigurePending", true) == true) List.push_back(Item(Item::ConfigurePending, PkgIterator())); // for the progress -- cgit v1.2.3 From c6bc9735cf1486d40d85bba90cfc3aaa6537a9c0 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 10 Dec 2014 22:26:59 +0100 Subject: do not make PTY slave the controlling terminal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we have no controlling terminal opening a terminal will make this terminal our controller, which is a serious problem if this happens to be the pseudo terminal we created to run dpkg in as we will close this terminal at the end hanging ourself up in the process… The offending open is the one we do to have at least one slave fd open all the time, but for good measure, we apply the flag also to the slave fd opening in the child process as we set the controlling terminal explicitely here. This is a regression from 150bdc9ca5d656f9fba94d37c5f4f183b02bd746 with the slight twist that this usecase was silently broken before in that it wasn't logging the output in term.log (as a pseudo terminal wasn't created). Closes: 772641 --- apt-pkg/deb/dpkgpm.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 79120f6f5..8a8214c19 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1127,7 +1127,7 @@ void pkgDPkgPM::StartPtyMagic() on kfreebsd we get an incorrect ("step like") output then while it has no problem with closing all references… so to avoid platform specific code here we combine both and be happy once more */ - d->protect_slave_from_dying = open(d->slave, O_RDWR | O_CLOEXEC); + d->protect_slave_from_dying = open(d->slave, O_RDWR | O_CLOEXEC | O_NOCTTY); } } } @@ -1159,7 +1159,7 @@ void pkgDPkgPM::SetupSlavePtyMagic() if (setsid() == -1) _error->FatalE("setsid", "Starting a new session for child failed!"); - int const slaveFd = open(d->slave, O_RDWR); + int const slaveFd = open(d->slave, O_RDWR | O_NOCTTY); if (slaveFd == -1) _error->FatalE("open", _("Can not write log (%s)"), _("Is /dev/pts mounted?")); else if (ioctl(slaveFd, TIOCSCTTY, 0) < 0) -- cgit v1.2.3 From e18f6133b254db9e1dc7b202366b067b15a68123 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 10 Dec 2014 22:26:59 +0100 Subject: do not make PTY slave the controlling terminal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we have no controlling terminal opening a terminal will make this terminal our controller, which is a serious problem if this happens to be the pseudo terminal we created to run dpkg in as we will close this terminal at the end hanging ourself up in the process… The offending open is the one we do to have at least one slave fd open all the time, but for good measure, we apply the flag also to the slave fd opening in the child process as we set the controlling terminal explicitely here. This is a regression from 150bdc9ca5d656f9fba94d37c5f4f183b02bd746 with the slight twist that this usecase was silently broken before in that it wasn't logging the output in term.log (as a pseudo terminal wasn't created). Closes: 772641 --- apt-pkg/deb/dpkgpm.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index e36a52c3e..93a007d14 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1131,7 +1131,7 @@ void pkgDPkgPM::StartPtyMagic() on kfreebsd we get an incorrect ("step like") output then while it has no problem with closing all references… so to avoid platform specific code here we combine both and be happy once more */ - d->protect_slave_from_dying = open(d->slave, O_RDWR | O_CLOEXEC); + d->protect_slave_from_dying = open(d->slave, O_RDWR | O_CLOEXEC | O_NOCTTY); } } } @@ -1163,7 +1163,7 @@ void pkgDPkgPM::SetupSlavePtyMagic() if (setsid() == -1) _error->FatalE("setsid", "Starting a new session for child failed!"); - int const slaveFd = open(d->slave, O_RDWR); + int const slaveFd = open(d->slave, O_RDWR | O_NOCTTY); if (slaveFd == -1) _error->FatalE("open", _("Can not write log (%s)"), _("Is /dev/pts mounted?")); else if (ioctl(slaveFd, TIOCSCTTY, 0) < 0) -- cgit v1.2.3 From a2a75ff4516f7609f4c55b42270abb8d08943c60 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 18 Nov 2014 19:53:56 +0100 Subject: always run 'dpkg --configure -a' at the end of our dpkg callings dpkg checks now for dependencies before running triggers, so that packages can now end up in trigger states (especially those we are not touching at all with our calls) after apt is done running. The solution to this is trivial: Just tell dpkg to configure everything after we have (supposely) configured everything already. In the worst case this means dpkg will have to run a bunch of triggers, usually it will just do nothing though. The code to make this happen was already available, so we just flip a config option here to cause it to be run. This way we can keep pretending that triggers are an implementation detail of dpkg. --triggers-only would supposely work as well, but --configure is more robust in regards to future changes to dpkg and something we will hopefully make use of in future versions anyway (as it was planed at the time this and related options were implemented). Note that dpkg currently has a workaround implemented to allow upgrades to jessie to be clean, so that the test works before and after. Also note that test (compared to the one in the bug) drops the await test as its is considered a loop by dpkg now. Closes: 769609 --- apt-pkg/deb/dpkgpm.cc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 93a007d14..d54b7b50f 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1047,6 +1047,12 @@ void pkgDPkgPM::BuildPackagesProgressMap() PackagesTotal++; } } + /* one extra: We don't want the progress bar to reach 100%, especially not + if we call dpkg --configure --pending and process a bunch of triggers + while showing 100%. Also, spindown takes a while, so never reaching 100% + is way more correct than reaching 100% while still doing stuff even if + doing it this way is slightly bending the rules */ + ++PackagesTotal; } /*}}}*/ #if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR < 13) @@ -1280,9 +1286,8 @@ bool pkgDPkgPM::GoNoABIBreak(APT::Progress::PackageManager *progress) // support subpressing of triggers processing for special // cases like d-i that runs the triggers handling manually - bool const SmartConf = (_config->Find("PackageManager::Configure", "all") != "all"); bool const TriggersPending = _config->FindB("DPkg::TriggersPending", false); - if (_config->FindB("DPkg::ConfigurePending", SmartConf) == true) + if (_config->FindB("DPkg::ConfigurePending", true) == true) List.push_back(Item(Item::ConfigurePending, PkgIterator())); // for the progress -- cgit v1.2.3 From 748a2177dcf8ff72bca90f5c7d516559ddd67352 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 22 Dec 2014 23:14:08 +0100 Subject: pass-through stdin fd instead of content if not a terminal Commit 299aea924ccef428219ed6f1a026c122678429e6 fixes the problem of not logging terminal in case stdin & stdout are not a terminal. The problem is that we are then trying to pass-through stdin content by reading from the apt-process stdin and writing it to the stdin of the child (dpkg), which works great for users who can control themselves, but pipes and co are a bit less forgiving causing us to pass everything to the first child process, which if the sending part of the pipe is e.g. 'yes' we will never see the end of it (as the pipe is full at some point and further writing blocks). There is a simple solution for that of course: If stdin isn't a terminal, we us the apt-process stdin as stdin for the child directly (We don't do this if it is a terminal to be able to save the typed input in the log). Closes: 773061 --- apt-pkg/deb/dpkgpm.cc | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index d54b7b50f..e23ca466d 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -73,7 +73,8 @@ public: pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0), term_out(NULL), history_out(NULL), progress(NULL), tt_is_valid(false), master(-1), - slave(NULL), protect_slave_from_dying(-1) + slave(NULL), protect_slave_from_dying(-1), + direct_stdin(false) { dpkgbuf[0] = '\0'; } @@ -100,6 +101,7 @@ public: sigset_t sigmask; sigset_t original_sigmask; + bool direct_stdin; }; namespace @@ -1079,6 +1081,9 @@ void pkgDPkgPM::StartPtyMagic() return; } + if (isatty(STDIN_FILENO) == 0) + d->direct_stdin = true; + _error->PushToStack(); d->master = posix_openpt(O_RDWR | O_NOCTTY); @@ -1176,7 +1181,10 @@ void pkgDPkgPM::SetupSlavePtyMagic() _error->FatalE("ioctl", "Setting TIOCSCTTY for slave fd %d failed!", slaveFd); else { - for (unsigned short i = 0; i < 3; ++i) + unsigned short i = 0; + if (d->direct_stdin == true) + ++i; + for (; i < 3; ++i) if (dup2(slaveFd, i) == -1) _error->FatalE("dup2", "Dupping %d to %d in child failed!", slaveFd, i); @@ -1596,8 +1604,8 @@ bool pkgDPkgPM::GoNoABIBreak(APT::Progress::PackageManager *progress) // wait for input or output here FD_ZERO(&rfds); - if (d->master >= 0 && !d->stdin_is_dev_null) - FD_SET(0, &rfds); + if (d->master >= 0 && d->direct_stdin == false && d->stdin_is_dev_null == false) + FD_SET(STDIN_FILENO, &rfds); FD_SET(_dpkgin, &rfds); if(d->master >= 0) FD_SET(d->master, &rfds); -- cgit v1.2.3 From 77b6f202e1629b7794a03b6522d636ff1436d074 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 10 Jan 2015 12:31:18 +0100 Subject: award points for positive dependencies again Commit 9ec748ff103840c4c65471ca00d3b72984131ce4 from Feb 23 last year adds a version check after 8daf68e366fa9fa2794ae667f51562663856237c added 8 days earlier negative points for breaks/conflicts with the intended that only dependencies which are satisfied propagate points (aka: old conflicts do not). The implementation was needlessly complex and flawed through preventing positive dependencies from gaining points like they did before these commits making library transitions harder instead of simpler. It worked out anyhow most of the time out of pure 'luck' (and other ways of gaining points) or got miss attributed to being a temporary hick-up. Closes: 774924 --- apt-pkg/algorithms.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 608ec7fce..b83831053 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -468,7 +468,7 @@ void pkgProblemResolver::MakeScores() if (D->Version != 0) { pkgCache::VerIterator const IV = Cache[T].InstVerIter(Cache); - if (IV.end() == true || D.IsSatisfied(IV) != D.IsNegative()) + if (IV.end() == true || D.IsSatisfied(IV) == false) continue; } Scores[T->ID] += DepMap[D->Type]; -- cgit v1.2.3 From 2f6a2fbbdc9f76dc4eace83a427013f4e1c03afc Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 8 Jan 2015 21:07:37 +0100 Subject: properly implement pkgRecord::Parser for *.deb files Implementing FileName() works for most cases for us, but other frontends might need more and even for us its not very stable as the normal Jump() implementation is pretty bad on a deb file and produce errors on its own at times. So, replacing this makeshift with a complete implementation by mostly just shuffling code around. --- apt-pkg/deb/debindexfile.cc | 73 ++++++++++++++++-------------- apt-pkg/deb/debindexfile.h | 8 ++++ apt-pkg/deb/debrecords.cc | 108 ++++++++++++++++++++++---------------------- apt-pkg/deb/debrecords.h | 49 ++++++++++++-------- apt-pkg/tagfile.cc | 6 +-- 5 files changed, 133 insertions(+), 111 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index cecfe41a9..49c6e8cc0 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -34,6 +34,7 @@ #include #include +#include #include #include /*}}}*/ @@ -671,8 +672,7 @@ APT_CONST bool debStatusIndex::Exists() const } /*}}}*/ -// debDebPkgFile - Single .deb file /*{{{*/ -// --------------------------------------------------------------------- +// debDebPkgFile - Single .deb file /*{{{*/ debDebPkgFileIndex::debDebPkgFileIndex(std::string DebFile) : pkgIndexFile(true), DebFile(DebFile) { @@ -688,53 +688,56 @@ bool debDebPkgFileIndex::Exists() const { return FileExists(DebFile); } -bool debDebPkgFileIndex::Merge(pkgCacheGenerator& Gen, OpProgress* Prog) const +bool debDebPkgFileIndex::GetContent(std::ostream &content, std::string const &debfile) { - if(Prog) - Prog->SubProgress(0, "Reading deb file"); - - // get the control data out of the deb file vid dpkg -I - // ... can I haz libdpkg? - Configuration::Item const *Opts = _config->Tree("DPkg::Options"); - std::string dpkg = _config->Find("Dir::Bin::dpkg","dpkg"); + // 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 Args; Args.push_back(dpkg.c_str()); - if (Opts != 0) - { - Opts = Opts->Child; - for (; Opts != 0; Opts = Opts->Next) - { - if (Opts->Value.empty() == true) - continue; - Args.push_back(Opts->Value.c_str()); - } - } Args.push_back("-I"); - Args.push_back(DebFile.c_str()); + Args.push_back(debfile.c_str()); Args.push_back("control"); Args.push_back(NULL); FileFd PipeFd; pid_t Child; if(Popen((const char**)&Args[0], PipeFd, Child, FileFd::ReadOnly) == false) return _error->Error("Popen failed"); - // FIXME: static buffer - char buf[8*1024]; - unsigned long long n = 0; - if(PipeFd.Read(buf, sizeof(buf)-1, &n) == false) - return _error->Errno("read", "Failed to read dpkg pipe"); + + char buffer[1024]; + do { + unsigned long long actual = 0; + if (PipeFd.Read(buffer, sizeof(buffer)-1, &actual) == false) + return _error->Errno("read", "Failed to read dpkg pipe"); + if (actual == 0) + break; + buffer[actual] = '\0'; + content << buffer; + } while(true); ExecWait(Child, "Popen"); - // now write the control data to a tempfile + 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 +{ + if(Prog) + Prog->SubProgress(0, "Reading deb file"); + + // write the control data to a tempfile SPtr DebControl = GetTempFile("deb-file-" + flNotDir(DebFile)); if(DebControl == NULL) return false; - DebControl->Write(buf, n); - // append size of the file - FileFd Fd(DebFile, FileFd::ReadOnly); - string Size; - strprintf(Size, "Size: %llu\n", Fd.Size()); - DebControl->Write(Size.c_str(), Size.size()); - // and rewind for the listparser + std::ostringstream content; + if (GetContent(content, DebFile) == 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 @@ -838,7 +841,7 @@ class APT_HIDDEN debIFTypeDebPkgFile : public pkgIndexFile::Type public: virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const { - return new debDebFileRecordParser(File.FileName(),*File.Cache()); + return new debDebFileRecordParser(File.FileName()); }; debIFTypeDebPkgFile() {Label = "deb Package file";}; }; diff --git a/apt-pkg/deb/debindexfile.h b/apt-pkg/deb/debindexfile.h index 312e915f1..81914f203 100644 --- a/apt-pkg/deb/debindexfile.h +++ b/apt-pkg/deb/debindexfile.h @@ -177,6 +177,14 @@ class APT_HIDDEN debDebPkgFileIndex : public pkgIndexFile return DebFile; } + /** get the control (file) content of the deb file + * + * @param[out] content of the control file + * @param debfile is the filename of the .deb-file + * @return \b true if successful, otherwise \b false. + */ + static bool GetContent(std::ostream &content, std::string const &debfile); + // Interface for the Cache Generator virtual bool Exists() const; virtual bool HasPackages() const { diff --git a/apt-pkg/deb/debrecords.cc b/apt-pkg/deb/debrecords.cc index b41aa5584..335bcfda0 100644 --- a/apt-pkg/deb/debrecords.cc +++ b/apt-pkg/deb/debrecords.cc @@ -11,35 +11,35 @@ #include #include +#include #include #include #include #include #include #include +#include #include #include +#include #include #include #include + +#include /*}}}*/ using std::string; // RecordParser::debRecordParser - Constructor /*{{{*/ -// --------------------------------------------------------------------- -/* */ -debRecordParser::debRecordParser(string FileName,pkgCache &Cache) : - File(FileName,FileFd::ReadOnly, FileFd::Extension), - Tags(&File, std::max(Cache.Head().MaxVerFileSize, - Cache.Head().MaxDescFileSize) + 200) +debRecordParser::debRecordParser(string FileName,pkgCache &Cache) : + debRecordParserBase(), File(FileName, FileFd::ReadOnly, FileFd::Extension), + Tags(&File, std::max(Cache.Head().MaxVerFileSize, Cache.Head().MaxDescFileSize) + 200) { } /*}}}*/ // RecordParser::Jump - Jump to a specific record /*{{{*/ -// --------------------------------------------------------------------- -/* */ bool debRecordParser::Jump(pkgCache::VerFileIterator const &Ver) { return Tags.Jump(Section,Ver->Offset); @@ -49,32 +49,28 @@ bool debRecordParser::Jump(pkgCache::DescFileIterator const &Desc) return Tags.Jump(Section,Desc->Offset); } /*}}}*/ -// RecordParser::FileName - Return the archive filename on the site /*{{{*/ -// --------------------------------------------------------------------- -/* */ -string debRecordParser::FileName() +debRecordParser::~debRecordParser() {} + +// RecordParserBase::FileName - Return the archive filename on the site /*{{{*/ +string debRecordParserBase::FileName() { return Section.FindS("Filename"); } /*}}}*/ -// RecordParser::Name - Return the package name /*{{{*/ -// --------------------------------------------------------------------- -/* */ -string debRecordParser::Name() +// RecordParserBase::Name - Return the package name /*{{{*/ +string debRecordParserBase::Name() { return Section.FindS("Package"); } /*}}}*/ -// RecordParser::Homepage - Return the package homepage /*{{{*/ -// --------------------------------------------------------------------- -/* */ -string debRecordParser::Homepage() +// RecordParserBase::Homepage - Return the package homepage /*{{{*/ +string debRecordParserBase::Homepage() { return Section.FindS("Homepage"); } /*}}}*/ -// RecordParser::Hashes - return the available archive hashes /*{{{*/ -HashStringList debRecordParser::Hashes() const +// RecordParserBase::Hashes - return the available archive hashes /*{{{*/ +HashStringList debRecordParserBase::Hashes() const { HashStringList hashes; for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type) @@ -86,27 +82,20 @@ HashStringList debRecordParser::Hashes() const return hashes; } /*}}}*/ -// RecordParser::Maintainer - Return the maintainer email /*{{{*/ -// --------------------------------------------------------------------- -/* */ -string debRecordParser::Maintainer() +// RecordParserBase::Maintainer - Return the maintainer email /*{{{*/ +string debRecordParserBase::Maintainer() { return Section.FindS("Maintainer"); } /*}}}*/ -// RecordParser::RecordField - Return the value of an arbitrary field /*{{*/ -// --------------------------------------------------------------------- -/* */ -string debRecordParser::RecordField(const char *fieldName) +// RecordParserBase::RecordField - Return the value of an arbitrary field /*{{*/ +string debRecordParserBase::RecordField(const char *fieldName) { return Section.FindS(fieldName); } - - /*}}}*/ -// RecordParser::ShortDesc - Return a 1 line description /*{{{*/ -// --------------------------------------------------------------------- -/* */ -string debRecordParser::ShortDesc(std::string const &lang) + /*}}}*/ +// RecordParserBase::ShortDesc - Return a 1 line description /*{{{*/ +string debRecordParserBase::ShortDesc(std::string const &lang) { string const Res = LongDesc(lang); if (Res.empty() == true) @@ -117,10 +106,8 @@ string debRecordParser::ShortDesc(std::string const &lang) return string(Res,0,Pos); } /*}}}*/ -// RecordParser::LongDesc - Return a longer description /*{{{*/ -// --------------------------------------------------------------------- -/* */ -string debRecordParser::LongDesc(std::string const &lang) +// RecordParserBase::LongDesc - Return a longer description /*{{{*/ +string debRecordParserBase::LongDesc(std::string const &lang) { string orig; if (lang.empty() == true) @@ -162,12 +149,9 @@ string debRecordParser::LongDesc(std::string const &lang) } /*}}}*/ -static const char *SourceVerSeparators = " ()"; - -// RecordParser::SourcePkg - Return the source package name if any /*{{{*/ -// --------------------------------------------------------------------- -/* */ -string debRecordParser::SourcePkg() +static const char * const SourceVerSeparators = " ()"; +// RecordParserBase::SourcePkg - Return the source package name if any /*{{{*/ +string debRecordParserBase::SourcePkg() { string Res = Section.FindS("Source"); string::size_type Pos = Res.find_first_of(SourceVerSeparators); @@ -176,10 +160,8 @@ string debRecordParser::SourcePkg() return string(Res,0,Pos); } /*}}}*/ -// RecordParser::SourceVer - Return the source version number if present /*{{{*/ -// --------------------------------------------------------------------- -/* */ -string debRecordParser::SourceVer() +// RecordParserBase::SourceVer - Return the source version number if present /*{{{*/ +string debRecordParserBase::SourceVer() { string Pkg = Section.FindS("Source"); string::size_type Pos = Pkg.find_first_of(SourceVerSeparators); @@ -199,13 +181,29 @@ string debRecordParser::SourceVer() return string(Pkg, VerStart, VerEnd - VerStart); } /*}}}*/ -// RecordParser::GetRec - Return the whole record /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void debRecordParser::GetRec(const char *&Start,const char *&Stop) +// RecordParserBase::GetRec - Return the whole record /*{{{*/ +void debRecordParserBase::GetRec(const char *&Start,const char *&Stop) { Section.GetSection(Start,Stop); } /*}}}*/ +debRecordParserBase::~debRecordParserBase() {} -debRecordParser::~debRecordParser() {} +bool debDebFileRecordParser::LoadContent() +{ + // load content only once + if (controlContent.empty() == false) + return true; + + std::ostringstream content; + if (debDebPkgFileIndex::GetContent(content, debFileName) == false) + return false; + // add two newlines to make sure the scanner finds the section, + // which is usually done by pkgTagFile automatically if needed. + content << "\n\n"; + + controlContent = content.str(); + if (Section.Scan(controlContent.c_str(), controlContent.length()) == false) + return _error->Error(_("Unable to parse package file %s (%d)"), debFileName.c_str(), 3); + return true; +} diff --git a/apt-pkg/deb/debrecords.h b/apt-pkg/deb/debrecords.h index 7091c38e6..38e071940 100644 --- a/apt-pkg/deb/debrecords.h +++ b/apt-pkg/deb/debrecords.h @@ -25,21 +25,12 @@ #include #endif -class APT_HIDDEN debRecordParser : public pkgRecords::Parser +class APT_HIDDEN debRecordParserBase : public pkgRecords::Parser { - /** \brief dpointer placeholder (for later in case we need it) */ - void *d; - protected: - FileFd File; - pkgTagFile Tags; pkgTagSection Section; - - virtual bool Jump(pkgCache::VerFileIterator const &Ver); - virtual bool Jump(pkgCache::DescFileIterator const &Desc); - - public: + public: // These refer to the archive file for the Version virtual std::string FileName(); virtual std::string SourcePkg(); @@ -58,20 +49,42 @@ class APT_HIDDEN debRecordParser : public pkgRecords::Parser virtual std::string RecordField(const char *fieldName); virtual void GetRec(const char *&Start,const char *&Stop); - + + debRecordParserBase() : Parser() {} + virtual ~debRecordParserBase(); +}; + +class APT_HIDDEN debRecordParser : public debRecordParserBase +{ + protected: + FileFd File; + pkgTagFile Tags; + + virtual bool Jump(pkgCache::VerFileIterator const &Ver); + virtual bool Jump(pkgCache::DescFileIterator const &Desc); + + public: debRecordParser(std::string FileName,pkgCache &Cache); virtual ~debRecordParser(); }; // custom record parser that reads deb files directly -class APT_HIDDEN debDebFileRecordParser : public debRecordParser +class APT_HIDDEN debDebFileRecordParser : public debRecordParserBase { + 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(); } + public: - virtual std::string FileName() { - return File.Name(); - } - debDebFileRecordParser(std::string FileName,pkgCache &Cache) - : debRecordParser(FileName, Cache) {}; + virtual std::string FileName() { return debFileName; } + + debDebFileRecordParser(std::string FileName) + : debRecordParserBase(), debFileName(FileName) {}; }; #endif diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc index 590206f17..9c40c8c92 100644 --- a/apt-pkg/tagfile.cc +++ b/apt-pkg/tagfile.cc @@ -183,8 +183,8 @@ bool pkgTagFile::Step(pkgTagSection &Tag) break; if (Resize() == false) - return _error->Error(_("Unable to parse package file %s (1)"), - d->Fd.Name().c_str()); + return _error->Error(_("Unable to parse package file %s (%d)"), + d->Fd.Name().c_str(), 1); } while (Tag.Scan(d->Start,d->End - d->Start, false) == false); } @@ -283,7 +283,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 (2)"),d->Fd.Name().c_str()); + return _error->Error(_("Unable to parse package file %s (%d)"),d->Fd.Name().c_str(), 2); return true; } -- cgit v1.2.3 From 2b4cead3c8eb3afb5aa5390b88c511477a7628d8 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 9 Mar 2015 15:54:39 +0100 Subject: fix some new compiler warnings reported by gcc-5 Git-Dch: Ignore --- apt-pkg/cacheset.cc | 4 ++-- apt-pkg/cacheset.h | 4 +++- apt-pkg/cdrom.cc | 10 +++++----- apt-pkg/contrib/configuration.cc | 10 +++++----- apt-pkg/deb/debmetaindex.cc | 9 ++++++--- apt-pkg/sourcelist.cc | 2 +- 6 files changed, 22 insertions(+), 17 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/cacheset.cc b/apt-pkg/cacheset.cc index 9127a4064..0ad99713a 100644 --- a/apt-pkg/cacheset.cc +++ b/apt-pkg/cacheset.cc @@ -754,7 +754,7 @@ pkgCache::VerIterator CacheSetHelper::canNotGetCandInstVer(pkgCacheFile &Cache, /*}}}*/ /*}}}*/ // showPackageSelection - by selector and given pattern /*{{{*/ -APT_CONST void CacheSetHelper::showPackageSelection(pkgCache::PkgIterator const &pkg, enum PkgSelector const select, +void CacheSetHelper::showPackageSelection(pkgCache::PkgIterator const &pkg, enum PkgSelector const select, std::string const &pattern) { switch (select) { APT_IGNORE_DEPRECATED_PUSH @@ -784,7 +784,7 @@ APT_CONST void CacheSetHelper::showFnmatchSelection(pkgCache::PkgIterator const /*}}}*/ /*}}}*/ // showVersionSelection /*{{{*/ -APT_CONST void CacheSetHelper::showVersionSelection(pkgCache::PkgIterator const &Pkg, +void CacheSetHelper::showVersionSelection(pkgCache::PkgIterator const &Pkg, pkgCache::VerIterator const &Ver, enum VerSelector const select, std::string const &pattern) { switch (select) { APT_IGNORE_DEPRECATED_PUSH diff --git a/apt-pkg/cacheset.h b/apt-pkg/cacheset.h index 884e8b859..97aee8c2d 100644 --- a/apt-pkg/cacheset.h +++ b/apt-pkg/cacheset.h @@ -225,7 +225,9 @@ public: inline std::string FullName(bool const Pretty) const { return getPkg().FullName(Pretty); } inline std::string FullName() const { return getPkg().FullName(); } APT_DEPRECATED inline const char *Section() const { - APT_IGNORE_DEPRECATED(return getPkg().Section();) + APT_IGNORE_DEPRECATED_PUSH + return getPkg().Section(); + APT_IGNORE_DEPRECATED_POP } inline bool Purge() const {return getPkg().Purge(); } inline const char *Arch() const {return getPkg().Arch(); } diff --git a/apt-pkg/cdrom.cc b/apt-pkg/cdrom.cc index aaa7b82e0..5eccbe5de 100644 --- a/apt-pkg/cdrom.cc +++ b/apt-pkg/cdrom.cc @@ -466,7 +466,7 @@ bool pkgCdrom::WriteSourceList(string Name,vector &List,bool Source) // Open the stream for reading ifstream F((FileExists(File)?File.c_str():"/dev/null"), ios::in ); - if (!F != 0) + if (F.fail() == true) return _error->Errno("ifstream::ifstream","Opening %s",File.c_str()); string NewFile = File + ".new"; @@ -477,7 +477,7 @@ bool pkgCdrom::WriteSourceList(string Name,vector &List,bool Source) "Failed to open %s.new",File.c_str()); // Create a short uri without the path - string ShortURI = "cdrom:[" + Name + "]/"; + string ShortURI = "cdrom:[" + Name + "]/"; string ShortURI2 = "cdrom:" + Name + "/"; // For Compatibility string Type; @@ -485,12 +485,12 @@ bool pkgCdrom::WriteSourceList(string Name,vector &List,bool Source) Type = "deb-src"; else Type = "deb"; - + char Buffer[300]; int CurLine = 0; bool First = true; while (F.eof() == false) - { + { F.getline(Buffer,sizeof(Buffer)); CurLine++; if (F.fail() && !F.eof()) @@ -754,7 +754,7 @@ bool pkgCdrom::Add(pkgCdromStatus *log) /*{{{*/ FileExists(InfoDir + "/info") == true) { ifstream F((InfoDir + "/info").c_str()); - if (!F == 0) + if (F.good() == true) getline(F,Name); if (Name.empty() == false) diff --git a/apt-pkg/contrib/configuration.cc b/apt-pkg/contrib/configuration.cc index 483d5bb1b..42e35d32a 100644 --- a/apt-pkg/contrib/configuration.cc +++ b/apt-pkg/contrib/configuration.cc @@ -629,19 +629,19 @@ string Configuration::Item::FullTag(const Item *Stop) const tag/value. AsSectional enables Sectional parsing.*/ bool ReadConfigFile(Configuration &Conf,const string &FName,bool const &AsSectional, unsigned const &Depth) -{ +{ // Open the stream for reading - ifstream F(FName.c_str(),ios::in); - if (!F != 0) + ifstream F(FName.c_str(),ios::in); + if (F.fail() == true) return _error->Errno("ifstream::ifstream",_("Opening configuration file %s"),FName.c_str()); string LineBuffer; string Stack[100]; unsigned int StackPos = 0; - + // Parser state string ParentTag; - + int CurLine = 0; bool InComment = false; while (F.eof() == false) diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 81e067424..aa2db8149 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -402,9 +402,12 @@ class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type { // parse arch=, arch+= and arch-= settings map::const_iterator arch = Options.find("arch"); - vector Archs = - (arch != Options.end()) ? VectorizeString(arch->second, ',') : - APT::Configuration::getArchitectures(); + vector Archs; + if (arch != Options.end()) + Archs = VectorizeString(arch->second, ','); + else + Archs = APT::Configuration::getArchitectures(); + if ((arch = Options.find("arch+")) != Options.end()) { std::vector const plusArch = VectorizeString(arch->second, ','); diff --git a/apt-pkg/sourcelist.cc b/apt-pkg/sourcelist.cc index 7170e8b5b..8b960572b 100644 --- a/apt-pkg/sourcelist.cc +++ b/apt-pkg/sourcelist.cc @@ -331,7 +331,7 @@ bool pkgSourceList::ParseFileOldStyle(string File) { // Open the stream for reading ifstream F(File.c_str(),ios::in /*| ios::nocreate*/); - if (!F != 0) + if (F.fail() == true) return _error->Errno("ifstream::ifstream",_("Opening %s"),File.c_str()); // CNC:2003-12-10 - 300 is too short. -- cgit v1.2.3 From b209edfa318e89df31a2dcae82c3d72b48c1e77f Mon Sep 17 00:00:00 2001 From: Helmut Grohne Date: Mon, 9 Mar 2015 18:11:10 +0100 Subject: parse arch-qualified Provides correctly The underlying problem is that libapt-pkg does not correctly parse these provides. Internally, it creates a version named "baz:i386" with architecture amd64. Of course, such a package name is invalid and thus this version is completely inaccessible. Thus, this bug should not cause apt to accept a broken situation as valid. Nevertheless, it prevents using architecture qualified depends. Closes: 777071 --- apt-pkg/deb/deblistparser.cc | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 462818a03..49bc3adfc 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -853,10 +853,16 @@ bool debListParser::ParseProvides(pkgCache::VerIterator &Ver) while (1) { Start = ParseDepends(Start,Stop,Package,Version,Op); + const size_t archfound = Package.rfind(':'); if (Start == 0) return _error->Error("Problem parsing Provides line"); if (Op != pkgCache::Dep::NoOp && Op != pkgCache::Dep::Equals) { _error->Warning("Ignoring Provides line with non-equal DepCompareOp for package %s", Package.c_str()); + } 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) + return false; } else if ((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign) { if (NewProvidesAllArch(Ver, Package, Version) == false) return false; -- cgit v1.2.3 From 63b399509d46df71e8d16bd0d362eb23aa6558d7 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 7 Apr 2015 12:20:56 +0200 Subject: Fix crash in pkgDPkgPM::WriteApportReport(() (LP: #1436626) --- apt-pkg/deb/dpkgpm.cc | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index e23ca466d..b187efb40 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1900,8 +1900,19 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg) } } - // log the ordering - const char *ops_str[] = {"Install", "Configure","Remove","Purge"}; + // log the ordering, see dpkgpm.h and the "Ops" enum there + const char *ops_str[] = { + "Install", + "Configure", + "Remove", + "Purge", + "ConfigurePending", + "TriggersPending", + "reserved-1", + "reserved-2", + "reserved-3", + "reserved-4", + }; fprintf(report, "AptOrdering:\n"); for (vector::iterator I = List.begin(); I != List.end(); ++I) if ((*I).Pkg != NULL) -- cgit v1.2.3 From 66c3875df391b1120b43831efcbe88a78569fbfe Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 7 Apr 2015 16:58:44 +0200 Subject: avoid depends on std::string implementation for pkgAcquire::Item::Mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In /experimental this is resolved by deprecating Mode and moving to a new std::string, but that breaks ABI of course, so that was out of question. We can't change to a malloc/free style c-string either as Mode is public and hence a library user could be setting this as well. std::string implementors actually helped us out here with copy-on-write which means that while the variable "obviously" runs out of scope here, in reality you get the correct result as the string we work with here comes from the configuration in which it is still valid. Such a dependency on magic is bad of course, but its still interesting that only python3 seems to have an issue with it… With some silly explicit if-else assigning we can sidestep this issue while retaining the same output for 99.99% of all users (= noone actually configures additional compression algorithms which are also provided by repositories…), but even for these 0.01% its just a small change in the display as Mode can not be used for anything else. Example: apt/aptitude uses it in its 'update' implementations in the one-line progress at the bottom for specific items. Closes: 781858 --- apt-pkg/acquire-item.cc | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 253cbdaf7..0bcafdc5c 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -1194,8 +1194,18 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,string Hash, Desc.URI = decompProg + ":" + FileName; QueueURI(Desc); - // FIXME: this points to a c++ string that goes out of scope - Mode = decompProg.c_str(); + if (decompProg == "copy") + Mode = "copy"; + else if (decompProg == "xz") + Mode = "xz"; + else if (decompProg == "lzma") + Mode = "lzma"; + else if (decompProg == "bzip2") + Mode = "bzip2"; + else if (decompProg == "gzip") + Mode = "gzip"; + else + Mode = "decomp"; } /*}}}*/ // AcqIndexTrans::pkgAcqIndexTrans - Constructor /*{{{*/ -- cgit v1.2.3 From 3af3768e1a0ae8519ac85fbe1eb4494eeb076fa2 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 7 Apr 2015 12:20:56 +0200 Subject: fix crash in order writing in pkgDPkgPM::WriteApportReport() libapt can be configured to write various bits of information to a file creating a report via apport. This is disabled by default in Debian and apport residing only in /experimental so far, but Ubuntu and other derivatives have this (in some versions) enabled by default and there is no regression potentially here. The crash is caused by a mismatch of operations vs. strings for operations, so adding the missing strings for these operations solves the problem. [commit message by David Kalnischkies] LP: #1436626 --- apt-pkg/deb/dpkgpm.cc | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index e23ca466d..82e045fd3 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1900,8 +1900,15 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg) } } - // log the ordering - const char *ops_str[] = {"Install", "Configure","Remove","Purge"}; + // log the ordering, see dpkgpm.h and the "Ops" enum there + const char *ops_str[] = { + "Install", + "Configure", + "Remove", + "Purge", + "ConfigurePending", + "TriggersPending", + }; fprintf(report, "AptOrdering:\n"); for (vector::iterator I = List.begin(); I != List.end(); ++I) if ((*I).Pkg != NULL) -- cgit v1.2.3 From 7e9b7ea8236a79580c4ca47712558096d66bad53 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 7 Apr 2015 18:31:12 +0200 Subject: demote VectorizeString gcc attribute from const to pure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit g++-5 generates a slightly broken libapt which doesn't split architecture configurations correctly resulting in e.g. Packages files requested for the bogus architecture 'amd64,i386' instead of for amd64 and i386. The reason is an incorrectly applied attribute marking the function as const, while functions with pointer arguments are not allowed to be declared as such (note that char& is a char* in disguise). Demoting the attribute to pure fixes this issue – better would be dropping the & from char but that is an API change… Neither earlier g++ versions nor clang use this attribute to generate broken code, so we don't need a rebuild of dependencies or anything and g++-5 isn't even included in jessie, but the effect is so strange and apt popular enough to consider avoiding this problem anyhow. --- apt-pkg/contrib/strutl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h index 185cdc3fc..f4f80834b 100644 --- a/apt-pkg/contrib/strutl.h +++ b/apt-pkg/contrib/strutl.h @@ -79,7 +79,7 @@ bool TokSplitString(char Tok,char *Input,char **List, unsigned long ListMax); // split a given string by a char -std::vector VectorizeString(std::string const &haystack, char const &split) APT_CONST; +std::vector VectorizeString(std::string const &haystack, char const &split) APT_PURE; /* \brief Return a vector of strings from string "input" where "sep" * is used as the delimiter string. -- cgit v1.2.3 From b8eba208daebe3e3f235983e44da9c398d6f7a57 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 10 Mar 2015 14:11:54 +0100 Subject: reimplement the last uses of sprintf Working with strings c-style is complicated and error-prune, so by converting to c++ style we gain some simplicity and avoid buffer overflows by later extensions. Git-Dch: Ignore --- apt-pkg/contrib/cdromutl.cc | 31 +++++------ apt-pkg/contrib/strutl.cc | 126 +++++++++++++++++++------------------------- 2 files changed, 71 insertions(+), 86 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/cdromutl.cc b/apt-pkg/contrib/cdromutl.cc index 936e377fb..6eb917457 100644 --- a/apt-pkg/contrib/cdromutl.cc +++ b/apt-pkg/contrib/cdromutl.cc @@ -207,7 +207,6 @@ bool IdentCdrom(string CD,string &Res,unsigned int Version) /* Run over the directory, we assume that the reader order will never change as the media is read-only. In theory if the kernel did some sort of wacked caching this might not be true.. */ - char S[300]; for (struct dirent *Dir = readdir(D); Dir != 0; Dir = readdir(D)) { // Skip some files.. @@ -215,30 +214,32 @@ bool IdentCdrom(string CD,string &Res,unsigned int Version) strcmp(Dir->d_name,"..") == 0) continue; + std::string S; if (Version <= 1) { - sprintf(S,"%lu",(unsigned long)Dir->d_ino); + strprintf(S, "%lu", (unsigned long)Dir->d_ino); } else { struct stat Buf; if (stat(Dir->d_name,&Buf) != 0) continue; - sprintf(S,"%lu",(unsigned long)Buf.st_mtime); + strprintf(S, "%lu", (unsigned long)Buf.st_mtime); } - - Hash.Add(S); + + Hash.Add(S.c_str()); Hash.Add(Dir->d_name); }; - + if (chdir(StartDir.c_str()) != 0) { _error->Errno("chdir",_("Unable to change to %s"),StartDir.c_str()); closedir(D); return false; } closedir(D); - + // Some stats from the fsys + std::string S; if (_config->FindB("Debug::identcdrom",false) == false) { struct statvfs Buf; @@ -248,19 +249,19 @@ bool IdentCdrom(string CD,string &Res,unsigned int Version) // We use a kilobyte block size to advoid overflow if (writable_media) { - sprintf(S,"%lu",(long)(Buf.f_blocks*(Buf.f_bsize/1024))); + strprintf(S, "%lu", (unsigned long)(Buf.f_blocks*(Buf.f_bsize/1024))); } else { - sprintf(S,"%lu %lu",(long)(Buf.f_blocks*(Buf.f_bsize/1024)), - (long)(Buf.f_bfree*(Buf.f_bsize/1024))); + strprintf(S, "%lu %lu", (unsigned long)(Buf.f_blocks*(Buf.f_bsize/1024)), + (unsigned long)(Buf.f_bfree*(Buf.f_bsize/1024))); } - Hash.Add(S); - sprintf(S,"-%u",Version); + Hash.Add(S.c_str()); + strprintf(S, "-%u", Version); } else - sprintf(S,"-%u.debug",Version); - + strprintf(S, "-%u.debug", Version); + Res = Hash.Result().Value() + S; - return true; + return true; } /*}}}*/ // FindMountPointForDevice - Find mountpoint for the given device /*{{{*/ diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index 0ac587a9e..0db4c57b2 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -324,21 +324,19 @@ bool ParseCWord(const char *&String,string &Res) /* */ string QuoteString(const string &Str, const char *Bad) { - string Res; + std::stringstream Res; for (string::const_iterator I = Str.begin(); I != Str.end(); ++I) { - if (strchr(Bad,*I) != 0 || isprint(*I) == 0 || + if (strchr(Bad,*I) != 0 || isprint(*I) == 0 || *I == 0x25 || // percent '%' char *I <= 0x20 || *I >= 0x7F) // control chars { - char Buf[10]; - sprintf(Buf,"%%%02x",(int)*I); - Res += Buf; + ioprintf(Res,"%%%02x",(int)*I); } else - Res += *I; + Res << *I; } - return Res; + return Res.str(); } /*}}}*/ // DeQuoteString - Convert a string from quoted from /*{{{*/ @@ -379,13 +377,12 @@ string DeQuoteString(string::const_iterator const &begin, YottaBytes (E24) */ string SizeToStr(double Size) { - char S[300]; double ASize; if (Size >= 0) ASize = Size; else ASize = -1*Size; - + /* bytes, KiloBytes, MegaBytes, GigaBytes, TeraBytes, PetaBytes, ExaBytes, ZettaBytes, YottaBytes */ char Ext[] = {'\0','k','M','G','T','P','E','Z','Y'}; @@ -394,20 +391,21 @@ string SizeToStr(double Size) { if (ASize < 100 && I != 0) { - sprintf(S,"%'.1f %c",ASize,Ext[I]); - break; + std::string S; + strprintf(S, "%'.1f %c", ASize, Ext[I]); + return S; } - + if (ASize < 10000) { - sprintf(S,"%'.0f %c",ASize,Ext[I]); - break; + std::string S; + strprintf(S, "%'.0f %c", ASize, Ext[I]); + return S; } ASize /= 1000.0; I++; } - - return S; + return ""; } /*}}}*/ // TimeToStr - Convert the time into a string /*{{{*/ @@ -415,36 +413,27 @@ string SizeToStr(double Size) /* Converts a number of seconds to a hms format */ string TimeToStr(unsigned long Sec) { - char S[300]; - - while (1) + std::string S; + if (Sec > 60*60*24) { - if (Sec > 60*60*24) - { - //d means days, h means hours, min means minutes, s means seconds - sprintf(S,_("%lid %lih %limin %lis"),Sec/60/60/24,(Sec/60/60) % 24,(Sec/60) % 60,Sec % 60); - break; - } - - if (Sec > 60*60) - { - //h means hours, min means minutes, s means seconds - sprintf(S,_("%lih %limin %lis"),Sec/60/60,(Sec/60) % 60,Sec % 60); - break; - } - - if (Sec > 60) - { - //min means minutes, s means seconds - sprintf(S,_("%limin %lis"),Sec/60,Sec % 60); - break; - } - - //s means seconds - sprintf(S,_("%lis"),Sec); - break; + //TRANSLATOR: d means days, h means hours, min means minutes, s means seconds + strprintf(S,_("%lid %lih %limin %lis"),Sec/60/60/24,(Sec/60/60) % 24,(Sec/60) % 60,Sec % 60); + } + else if (Sec > 60*60) + { + //TRANSLATOR: h means hours, min means minutes, s means seconds + strprintf(S,_("%lih %limin %lis"),Sec/60/60,(Sec/60) % 60,Sec % 60); + } + else if (Sec > 60) + { + //TRANSLATOR: min means minutes, s means seconds + strprintf(S,_("%limin %lis"),Sec/60,Sec % 60); + } + else + { + //TRANSLATOR: s means seconds + strprintf(S,_("%lis"),Sec); } - return S; } /*}}}*/ @@ -1423,7 +1412,7 @@ size_t strv_length(const char **str_array) ; return i; } - + /*}}}*/ // DeEscapeString - unescape (\0XX and \xXX) from a string /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -1605,51 +1594,46 @@ void URI::CopyFrom(const string &U) /* */ URI::operator string() { - string Res; - + std::stringstream Res; + if (Access.empty() == false) - Res = Access + ':'; - + Res << Access << ':'; + if (Host.empty() == false) - { + { if (Access.empty() == false) - Res += "//"; - + Res << "//"; + if (User.empty() == false) { // FIXME: Technically userinfo is permitted even less // characters than these, but this is not conveniently // expressed with a blacklist. - Res += QuoteString(User, ":/?#[]@"); + Res << QuoteString(User, ":/?#[]@"); if (Password.empty() == false) - Res += ":" + QuoteString(Password, ":/?#[]@"); - Res += "@"; + Res << ":" << QuoteString(Password, ":/?#[]@"); + Res << "@"; } - + // Add RFC 2732 escaping characters - if (Access.empty() == false && - (Host.find('/') != string::npos || Host.find(':') != string::npos)) - Res += '[' + Host + ']'; + if (Access.empty() == false && Host.find_first_of("/:") != string::npos) + Res << '[' << Host << ']'; else - Res += Host; - + Res << Host; + if (Port != 0) - { - char S[30]; - sprintf(S,":%u",Port); - Res += S; - } + Res << ':' << Port; } - + if (Path.empty() == false) { if (Path[0] != '/') - Res += "/" + Path; + Res << "/" << Path; else - Res += Path; + Res << Path; } - - return Res; + + return Res.str(); } /*}}}*/ // URI::SiteOnly - Return the schema and site for the URI /*{{{*/ -- cgit v1.2.3 From 596ec43ce34421080a58b28299c1ed9cb0dbaa25 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 12 Apr 2015 19:16:01 +0200 Subject: parse specific-arch dependencies correctly on single-arch systems MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On single-arch the parsing was creating groupnames like 'apt:amd64' even through it should be 'apt' and a package in it belonging to architecture amd64. The result for foreign architectures was as expected: The dependency isn't satisfiable, but for native architecture it means the wrong package (ala apt:amd64:amd64) is linked so this is also not satisfiable, which is very much not expected. No longer excluding single-arch from this codepath allows the generation of the correct links, which still link to non-exisiting packages for foreign dependencies, but natives link to the expected native package just as if no architecture was given. For negative arch-specific dependencies ala Conflicts this matter was worse as apt will believe there isn't a Conflict to resolve, tricking it into calculating a solution dpkg will refuse. Architecture specific positive dependencies are rare in jessie – the only one in amd64 main is foreign –, negative dependencies do not even exist. Neither class has a native specimen, so no package in jessie is effected by this bug, but it might be interesting for stretch upgrades. This also means the regression potential is very low. Closes: 777760 --- apt-pkg/deb/deblistparser.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 4eef66c2b..213235c2b 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -770,7 +770,7 @@ bool debListParser::ParseDepends(pkgCache::VerIterator &Ver, if (NewDepends(Ver,Package,"none",Version,Op,Type) == false) return false; } - else if (MultiArchEnabled == true && found != string::npos && + else if (found != string::npos && strcmp(Package.c_str() + found, ":any") != 0) { string Arch = Package.substr(found+1, string::npos); -- cgit v1.2.3 From 76cbc9abb2d09ee5b248dfaa24948ba016fb6dee Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 30 Mar 2015 14:37:43 +0200 Subject: if we can, use gccs __builtin_swap methods Git-Dch: Ignore --- apt-pkg/contrib/sha2_internal.cc | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/sha2_internal.cc b/apt-pkg/contrib/sha2_internal.cc index 131ff5beb..f70b7b17d 100644 --- a/apt-pkg/contrib/sha2_internal.cc +++ b/apt-pkg/contrib/sha2_internal.cc @@ -129,6 +129,14 @@ typedef u_int64_t sha2_word64; /* Exactly 8 bytes */ /*** ENDIAN REVERSAL MACROS *******************************************/ #if BYTE_ORDER == LITTLE_ENDIAN +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) +#define REVERSE32(w,x) { \ + (x) = __builtin_bswap32(w); \ +} +#define REVERSE64(w,x) { \ + (x) = __builtin_bswap64(w); \ +} +#else #define REVERSE32(w,x) { \ sha2_word32 tmp = (w); \ tmp = (tmp >> 16) | (tmp << 16); \ @@ -142,6 +150,7 @@ typedef u_int64_t sha2_word64; /* Exactly 8 bytes */ (x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \ ((tmp & 0x0000ffff0000ffffULL) << 16); \ } +#endif #endif /* BYTE_ORDER == LITTLE_ENDIAN */ /* -- cgit v1.2.3 From 9224ce3d4d1ea0428a70e75134998e08aa45b1e6 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 30 Mar 2015 20:47:13 +0200 Subject: calculate only expected hashes in methods Methods get told which hashes are expected by the acquire system, which means we can use this list to restrict what we calculate in the methods as any extra we are calculating is wasted effort as we can't compare it with anything anyway. Adding support for a new hash algorithm is therefore 'free' now and if a algorithm is no longer provided in a repository for a file, we automatically stop calculating it. In practice this results in a speed-up in Debian as we don't have SHA512 here (so far), so we practically stop calculating it. --- apt-pkg/contrib/hashes.cc | 63 ++++++++++++++++++++++++++++++++++++----------- apt-pkg/contrib/hashes.h | 21 +++++++++++++--- 2 files changed, 65 insertions(+), 19 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/hashes.cc b/apt-pkg/contrib/hashes.cc index 6e7080bc9..953465091 100644 --- a/apt-pkg/contrib/hashes.cc +++ b/apt-pkg/contrib/hashes.cc @@ -250,28 +250,34 @@ bool HashStringList::operator!=(HashStringList const &other) const class PrivateHashes { public: unsigned long long FileSize; + unsigned int CalcHashes; - PrivateHashes() : FileSize(0) {} + PrivateHashes(unsigned int const CalcHashes) : FileSize(0), CalcHashes(CalcHashes) {} }; /*}}}*/ // Hashes::Add* - Add the contents of data or FD /*{{{*/ -bool Hashes::Add(const unsigned char * const Data,unsigned long long const Size, unsigned int const Hashes) +bool Hashes::Add(const unsigned char * const Data, unsigned long long const Size) { bool Res = true; APT_IGNORE_DEPRECATED_PUSH - if ((Hashes & MD5SUM) == MD5SUM) + if ((d->CalcHashes & MD5SUM) == MD5SUM) Res &= MD5.Add(Data, Size); - if ((Hashes & SHA1SUM) == SHA1SUM) + if ((d->CalcHashes & SHA1SUM) == SHA1SUM) Res &= SHA1.Add(Data, Size); - if ((Hashes & SHA256SUM) == SHA256SUM) + if ((d->CalcHashes & SHA256SUM) == SHA256SUM) Res &= SHA256.Add(Data, Size); - if ((Hashes & SHA512SUM) == SHA512SUM) + if ((d->CalcHashes & SHA512SUM) == SHA512SUM) Res &= SHA512.Add(Data, Size); APT_IGNORE_DEPRECATED_POP d->FileSize += Size; return Res; } -bool Hashes::AddFD(int const Fd,unsigned long long Size, unsigned int const Hashes) +bool Hashes::Add(const unsigned char * const Data, unsigned long long const Size, unsigned int const Hashes) +{ + d->CalcHashes = Hashes; + return Add(Data, Size); +} +bool Hashes::AddFD(int const Fd,unsigned long long Size) { unsigned char Buf[64*64]; bool const ToEOF = (Size == UntilEOF); @@ -285,12 +291,17 @@ bool Hashes::AddFD(int const Fd,unsigned long long Size, unsigned int const Hash if (ToEOF && Res == 0) // EOF break; Size -= Res; - if (Add(Buf, Res, Hashes) == false) + if (Add(Buf, Res) == false) return false; } return true; } -bool Hashes::AddFD(FileFd &Fd,unsigned long long Size, unsigned int const Hashes) +bool Hashes::AddFD(int const Fd,unsigned long long Size, unsigned int const Hashes) +{ + d->CalcHashes = Hashes; + return AddFD(Fd, Size); +} +bool Hashes::AddFD(FileFd &Fd,unsigned long long Size) { unsigned char Buf[64*64]; bool const ToEOF = (Size == 0); @@ -309,20 +320,29 @@ bool Hashes::AddFD(FileFd &Fd,unsigned long long Size, unsigned int const Hashes else if (a == 0) // EOF break; Size -= a; - if (Add(Buf, a, Hashes) == false) + if (Add(Buf, a) == false) return false; } return true; +} +bool Hashes::AddFD(FileFd &Fd,unsigned long long Size, unsigned int const Hashes) +{ + d->CalcHashes = Hashes; + return AddFD(Fd, Size); } /*}}}*/ HashStringList Hashes::GetHashStringList() { HashStringList hashes; APT_IGNORE_DEPRECATED_PUSH - hashes.push_back(HashString("MD5Sum", MD5.Result().Value())); - hashes.push_back(HashString("SHA1", SHA1.Result().Value())); - hashes.push_back(HashString("SHA256", SHA256.Result().Value())); - hashes.push_back(HashString("SHA512", SHA512.Result().Value())); + if ((d->CalcHashes & MD5SUM) == MD5SUM) + hashes.push_back(HashString("MD5Sum", MD5.Result().Value())); + if ((d->CalcHashes & SHA1SUM) == SHA1SUM) + hashes.push_back(HashString("SHA1", SHA1.Result().Value())); + if ((d->CalcHashes & SHA256SUM) == SHA256SUM) + hashes.push_back(HashString("SHA256", SHA256.Result().Value())); + 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); @@ -330,6 +350,19 @@ APT_IGNORE_DEPRECATED_POP return hashes; } APT_IGNORE_DEPRECATED_PUSH -Hashes::Hashes() { d = new PrivateHashes(); } +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() { delete d; } APT_IGNORE_DEPRECATED_POP diff --git a/apt-pkg/contrib/hashes.h b/apt-pkg/contrib/hashes.h index 154862457..ac13c8ace 100644 --- a/apt-pkg/contrib/hashes.h +++ b/apt-pkg/contrib/hashes.h @@ -178,7 +178,8 @@ class Hashes static const int UntilEOF = 0; - bool Add(const unsigned char * const Data, unsigned long long const Size, unsigned int const Hashes = ~0); + bool Add(const unsigned char * const Data, unsigned long long const Size); + APT_DEPRECATED bool Add(const unsigned char * const Data, unsigned long long const Size, unsigned int const Hashes); inline bool Add(const char * const Data) {return Add((unsigned char const * const)Data,strlen(Data));}; inline bool Add(const unsigned char * const Beg,const unsigned char * const End) @@ -186,13 +187,24 @@ class Hashes enum SupportedHashes { MD5SUM = (1 << 0), SHA1SUM = (1 << 1), SHA256SUM = (1 << 2), SHA512SUM = (1 << 3) }; - bool AddFD(int const Fd,unsigned long long Size = 0, unsigned int const Hashes = ~0); - bool AddFD(FileFd &Fd,unsigned long long Size = 0, unsigned int const Hashes = ~0); + bool AddFD(int const Fd,unsigned long long Size = 0); + APT_DEPRECATED bool AddFD(int const Fd,unsigned long long Size, unsigned int const Hashes); + bool AddFD(FileFd &Fd,unsigned long long Size = 0); + APT_DEPRECATED bool AddFD(FileFd &Fd,unsigned long long Size, unsigned int const Hashes); HashStringList GetHashStringList(); APT_IGNORE_DEPRECATED_PUSH + /** create a Hashes object to calculate all supported hashes + * + * If ALL is too much, you can limit which Hashes are calculated + * with the following other constructors which mention explicitly + * which hashes to generate. */ Hashes(); + /** @param Hashes bitflag composed of #SupportedHashes */ + Hashes(unsigned int const Hashes); + /** @param Hashes is a list of hashes */ + Hashes(HashStringList const &Hashes); virtual ~Hashes(); APT_IGNORE_DEPRECATED_POP @@ -208,15 +220,16 @@ APT_IGNORE_DEPRECATED_POP } public: +APT_IGNORE_DEPRECATED_PUSH APT_DEPRECATED bool AddFD(int const Fd, unsigned long long Size, bool const addMD5, bool const addSHA1, bool const addSHA256, bool const addSHA512) { return AddFD(Fd, Size, boolsToFlag(addMD5, addSHA1, addSHA256, addSHA512)); }; - APT_DEPRECATED bool AddFD(FileFd &Fd, unsigned long long Size, bool const addMD5, bool const addSHA1, bool const addSHA256, bool const addSHA512) { return AddFD(Fd, Size, boolsToFlag(addMD5, addSHA1, addSHA256, addSHA512)); }; +APT_IGNORE_DEPRECATED_POP }; #endif -- cgit v1.2.3 From d84da4995df24329e96d57a22136683a9e370f4e Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 11 Apr 2015 20:13:19 +0200 Subject: ensure lists/ files have correct permissions after apt-cdrom add Its a bit unpredictable which permissons and owners we will encounter on a CD-ROM (or a USB stick, as apt-cdrom is responsible for those too), so we have to ensure in this codepath as well that everything is nicely setup without waiting for a 'apt-get update' to fix up the (potential) mess. --- apt-pkg/acquire-worker.cc | 14 -------------- apt-pkg/cdrom.cc | 13 ++++--------- apt-pkg/contrib/fileutl.cc | 19 +++++++++++++++++++ apt-pkg/contrib/fileutl.h | 13 ++++++++++++- apt-pkg/indexcopy.cc | 5 ++++- 5 files changed, 39 insertions(+), 25 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-worker.cc b/apt-pkg/acquire-worker.cc index f4d1ad412..bee01e620 100644 --- a/apt-pkg/acquire-worker.cc +++ b/apt-pkg/acquire-worker.cc @@ -43,20 +43,6 @@ using namespace std; -static void ChangeOwnerAndPermissionOfFile(char const * const requester, char const * const file, char const * const user, char const * const group, mode_t const mode) /*{{{*/ -{ - if (getuid() == 0 && strlen(user) != 0 && strlen(group) != 0) // if we aren't root, we can't chown, so don't try it - { - // ensure the file is owned by root and has good permissions - struct passwd const * const pw = getpwnam(user); - struct group const * const gr = getgrnam(group); - if (pw != NULL && gr != NULL && chown(file, pw->pw_uid, gr->gr_gid) != 0) - _error->WarningE(requester, "chown to %s:%s of file %s failed", user, group, file); - } - if (chmod(file, mode) != 0) - _error->WarningE(requester, "chmod 0%o of file %s failed", mode, file); -} - /*}}}*/ // Worker::Worker - Constructor for Queue startup /*{{{*/ // --------------------------------------------------------------------- /* */ diff --git a/apt-pkg/cdrom.cc b/apt-pkg/cdrom.cc index 5eccbe5de..8cec4b78e 100644 --- a/apt-pkg/cdrom.cc +++ b/apt-pkg/cdrom.cc @@ -927,8 +927,7 @@ pkgUdevCdromDevices::pkgUdevCdromDevices() /*{{{*/ } /*}}}*/ -bool -pkgUdevCdromDevices::Dlopen() /*{{{*/ +bool pkgUdevCdromDevices::Dlopen() /*{{{*/ { // alread open if(libudev_handle != NULL) @@ -957,18 +956,14 @@ pkgUdevCdromDevices::Dlopen() /*{{{*/ return true; } /*}}}*/ - /*{{{*/ -// convenience interface, this will just call ScanForRemovable -vector -pkgUdevCdromDevices::Scan() +// convenience interface, this will just call ScanForRemovable /*{{{*/ +vector pkgUdevCdromDevices::Scan() { bool CdromOnly = _config->FindB("APT::cdrom::CdromOnly", true); return ScanForRemovable(CdromOnly); } /*}}}*/ - /*{{{*/ -vector -pkgUdevCdromDevices::ScanForRemovable(bool CdromOnly) +vector pkgUdevCdromDevices::ScanForRemovable(bool CdromOnly)/*{{{*/ { vector cdrom_devices; struct udev_enumerate *enumerate; diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 47033eadf..afc243b7f 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -874,6 +874,25 @@ bool StartsWithGPGClearTextSignature(string const &FileName) return true; } /*}}}*/ +// ChangeOwnerAndPermissionOfFile - set file attributes to requested values /*{{{*/ +bool ChangeOwnerAndPermissionOfFile(char const * const requester, char const * const file, char const * const user, char const * const group, mode_t const mode) +{ + if (strcmp(file, "/dev/null") == 0) + return true; + bool Res = true; + if (getuid() == 0 && strlen(user) != 0 && strlen(group) != 0) // if we aren't root, we can't chown, so don't try it + { + // ensure the file is owned by root and has good permissions + struct passwd const * const pw = getpwnam(user); + struct group const * const gr = getgrnam(group); + if (pw != NULL && gr != NULL && chown(file, pw->pw_uid, gr->gr_gid) != 0) + Res &= _error->WarningE(requester, "chown to %s:%s of file %s failed", user, group, file); + } + if (chmod(file, mode) != 0) + Res &= _error->WarningE(requester, "chmod 0%o of file %s failed", mode, file); + return Res; +} + /*}}}*/ class FileFdPrivate { /*{{{*/ public: diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h index a64d6cb98..97cb05c56 100644 --- a/apt-pkg/contrib/fileutl.h +++ b/apt-pkg/contrib/fileutl.h @@ -195,10 +195,21 @@ pid_t ExecFork(std::set keep_fds); void MergeKeepFdsFromConfiguration(std::set &keep_fds); bool ExecWait(pid_t Pid,const char *Name,bool Reap = false); - // check if the given file starts with a PGP cleartext signature bool StartsWithGPGClearTextSignature(std::string const &FileName); +/** change file attributes to requested known good values + * + * The method skips the user:group setting if not root. + * + * @param requester is printed as functionname in error cases + * @param file is the file to be modified + * @param user is the (new) owner of the file, e.g. _apt + * @param group is the (new) group owning the file, e.g. root + * @param mode is the access mode of the file, e.g. 0644 + */ +bool ChangeOwnerAndPermissionOfFile(char const * const requester, char const * const file, char const * const user, char const * const group, mode_t const mode); + /** * \brief Drop privileges * diff --git a/apt-pkg/indexcopy.cc b/apt-pkg/indexcopy.cc index 5fa57fd8b..144c508be 100644 --- a/apt-pkg/indexcopy.cc +++ b/apt-pkg/indexcopy.cc @@ -216,6 +216,7 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector &List, FinalF += URItoFileName(S); if (rename(TargetF.c_str(),FinalF.c_str()) != 0) return _error->Errno("rename","Failed to rename"); + ChangeOwnerAndPermissionOfFile("CopyPackages", FinalF.c_str(), "root", "root", 0644); } /* Mangle the source to be in the proper notation with @@ -546,8 +547,9 @@ bool SigVerify::CopyMetaIndex(string CDROM, string CDName, /*{{{*/ FileFd Rel; Target.Open(TargetF,FileFd::WriteAtomic); Rel.Open(prefix + file,FileFd::ReadOnly); - if (CopyFile(Rel,Target) == false) + if (CopyFile(Rel,Target) == false || Target.Close() == false) return _error->Error("Copying of '%s' for '%s' from '%s' failed", file.c_str(), CDName.c_str(), prefix.c_str()); + ChangeOwnerAndPermissionOfFile("CopyPackages", TargetF.c_str(), "root", "root", 0644); return true; } @@ -760,6 +762,7 @@ bool TranslationsCopy::CopyTranslations(string CDROM,string Name, /*{{{*/ FinalF += URItoFileName(S); if (rename(TargetF.c_str(),FinalF.c_str()) != 0) return _error->Errno("rename","Failed to rename"); + ChangeOwnerAndPermissionOfFile("CopyTranslations", FinalF.c_str(), "root", "root", 0644); } -- cgit v1.2.3 From de1c9b8ad208ae677fc6e916a907e319f246b1e8 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 12 Apr 2015 11:20:55 +0200 Subject: unsigned Release files can expire, too Checking Valid-Until on an unsigned Release file doesn't give us any security brownie points as an attacker could just change the date and in practice repositories with unsigned Release files will very likely not have a Valid-Until date, but for symetry and the fact that being unsigned is currently just a warning, while expired is a fatal error. --- apt-pkg/acquire-item.cc | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index dd85fda79..bdbdcc456 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -1739,7 +1739,10 @@ void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)/*{{{*/ // we parse the indexes here because at this point the user wanted // a repository that may potentially harm him MetaIndexParser->Load(MetaIndexFile); - QueueIndexes(true); + if (!VerifyVendor(Message, RealURI)) + /* expired Release files are still a problem you need extra force for */; + else + QueueIndexes(true); } // FIXME: this is used often (e.g. in pkgAcqIndexTrans) so refactor @@ -1843,6 +1846,7 @@ bool pkgAcqMetaBase::CheckAuthDone(string Message, const string &RealURI) /*{{{* if (!VerifyVendor(Message, RealURI)) { + Status = StatAuthError; return false; } @@ -2030,13 +2034,19 @@ bool pkgAcqMetaBase::VerifyVendor(string Message, const string &RealURI)/*{{{*/ MetaIndexParser->GetValidUntil() > 0) { time_t const invalid_since = time(NULL) - MetaIndexParser->GetValidUntil(); if (invalid_since > 0) - // 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) - return _error->Error( - _("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()); + { + 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()); + } } if (_config->FindB("Debug::pkgAcquire::Auth", false)) -- cgit v1.2.3 From 295d848b37e1211feae5d37db27f148dc9ea3d38 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 12 Apr 2015 14:32:12 +0200 Subject: refactor calculation of final lists/ name from URI Calculating the final name of an item which it will have after everything is done and verified successfully is suprisingly complicated as while they all follow a simple pattern, the URI and where it is stored varies between the items. With some (abibreaking) redesign we can abstract this similar to how it is already down for the partial file location. Git-Dch: Ignore --- apt-pkg/acquire-item.cc | 193 ++++++++++++++++++++---------------------------- apt-pkg/acquire-item.h | 83 +++++++++++---------- 2 files changed, 124 insertions(+), 152 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index bdbdcc456..f30529066 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -74,6 +74,11 @@ static std::string GetPartialFileNameFromURI(std::string const &uri) /*{{{*/ return GetPartialFileName(URItoFileName(uri)); } /*}}}*/ +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) /*{{{*/ { if (Ext.empty() || Ext == "uncompressed") @@ -273,6 +278,12 @@ 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) @@ -348,8 +359,7 @@ pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner, std::clog << "pkgAcqDiffIndex: " << Desc.URI << std::endl; // look for the current package file - CurrentPackagesFile = _config->FindDir("Dir::State::lists"); - CurrentPackagesFile += URItoFileName(RealURI); + CurrentPackagesFile = GetFinalFileNameFromURI(RealURI); // FIXME: this file:/ check is a hack to prevent fetching // from local sources. this is really silly, and @@ -368,6 +378,13 @@ pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner, 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 /*{{{*/ @@ -379,8 +396,7 @@ string pkgAcqDiffIndex::Custom600Headers() const string pkgAcqDiffIndex::Custom600Headers() #endif { - string Final = _config->FindDir("Dir::State::lists"); - Final += URItoFileName(Desc.URI); + string const Final = GetFinalFilename(); if(Debug) std::clog << "Custom600Header-IMS: " << Final << std::endl; @@ -709,10 +725,7 @@ void pkgAcqDiffIndex::Done(string Message,unsigned long long Size,HashStringList } - string FinalFile; - FinalFile = _config->FindDir("Dir::State::lists"); - FinalFile += URItoFileName(Desc.URI); - + string const FinalFile = GetFinalFilename(); if(StringToBool(LookupTag(Message,"IMS-Hit"),false)) DestFile = FinalFile; @@ -754,8 +767,7 @@ pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire *Owner, if(available_patches.empty() == true) { // we are done (yeah!), check hashes against the final file - DestFile = _config->FindDir("Dir::State::lists"); - DestFile += URItoFileName(Target->URI); + DestFile = GetFinalFileNameFromURI(Target->URI); Finish(true); } else @@ -797,10 +809,7 @@ void pkgAcqIndexDiffs::Finish(bool allDone) return; } - // queue for copy - std::string FinalFile = _config->FindDir("Dir::State::lists"); - FinalFile += URItoFileName(RealURI); - TransactionManager->TransactionStageCopy(this, DestFile, FinalFile); + TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename()); // this is for the "real" finish Complete = true; @@ -1064,10 +1073,8 @@ void pkgAcqIndexMergeDiffs::Done(string Message,unsigned long long Size,HashStri } - std::string FinalFile = _config->FindDir("Dir::State::lists"); - FinalFile += URItoFileName(RealURI); - // move the result into place + std::string const FinalFile = GetFinalFilename(); if(Debug) std::clog << "Queue patched file in place: " << std::endl << DestFile << " -> " << FinalFile << std::endl; @@ -1106,6 +1113,12 @@ bool pkgAcqBaseIndex::VerifyHashByMetaKey(HashStringList const &Hashes) return true; } /*}}}*/ +// 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 @@ -1293,8 +1306,7 @@ void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf) // pkgAcqIndex::GetFinalFilename - Return the full final file path /*{{{*/ std::string pkgAcqIndex::GetFinalFilename() const { - std::string FinalFile = _config->FindDir("Dir::State::lists"); - FinalFile += URItoFileName(RealURI); + std::string const FinalFile = GetFinalFileNameFromURI(RealURI); return GetCompressedFileName(RealURI, FinalFile, CurrentCompressionExtension); } /*}}}*/ @@ -1566,18 +1578,16 @@ void pkgAcqMetaBase::TransactionStageRemoval(Item *I, const std::string &FinalFile) { I->PartialFile = ""; - I->DestFile = FinalFile; + I->DestFile = FinalFile; } /*}}}*/ // AcqMetaBase::GenerateAuthWarning - Check gpg authentication error /*{{{*/ -bool pkgAcqMetaBase::CheckStopAuthentication(const std::string &RealURI, - const std::string &Message) +bool pkgAcqMetaBase::CheckStopAuthentication(const std::string &Message) { // FIXME: this entire function can do now that we disallow going to // a unauthenticated state and can cleanly rollback - string Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI); - + string const Final = GetFinalFilename(); if(FileExists(Final)) { Status = StatTransientNetworkError; @@ -1613,13 +1623,12 @@ pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner, string MetaIndexFile, const vector* IndexTargets, indexRecords* MetaIndexParser) : - pkgAcqMetaBase(Owner, IndexTargets, MetaIndexParser, + pkgAcqMetaBase(Owner, IndexTargets, MetaIndexParser, URI, HashStringList(), TransactionManager), - RealURI(URI), MetaIndexFile(MetaIndexFile), URIDesc(URIDesc), + MetaIndexFile(MetaIndexFile), URIDesc(URIDesc), ShortDesc(ShortDesc) { - DestFile = _config->FindDir("Dir::State::lists") + "partial/"; - DestFile += URItoFileName(RealURI); + DestFile = GetPartialFileNameFromURI(RealURI); // remove any partial downloaded sig-file in partial/. // it may confuse proxies and is too small to warrant a @@ -1642,18 +1651,6 @@ pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner, /*}}}*/ pkgAcqMetaSig::~pkgAcqMetaSig() /*{{{*/ { -} - /*}}}*/ -// pkgAcqMetaSig::Custom600Headers - Insert custom request headers /*{{{*/ -// --------------------------------------------------------------------- -#if APT_PKG_ABI >= 413 -string pkgAcqMetaSig::Custom600Headers() const -#else -string pkgAcqMetaSig::Custom600Headers() -#endif -{ - std::string Header = GetCustom600Headers(RealURI); - return Header; } /*}}}*/ // pkgAcqMetaSig::Done - The signature was downloaded/verified /*{{{*/ @@ -1667,7 +1664,7 @@ void pkgAcqMetaSig::Done(string Message,unsigned long long Size, if(AuthPass == false) { - if(CheckDownloadDone(Message, RealURI) == true) + if(CheckDownloadDone(Message) == true) { // destfile will be modified to point to MetaIndexFile for the // gpgv method, so we need to save it here @@ -1676,15 +1673,8 @@ void pkgAcqMetaSig::Done(string Message,unsigned long long Size, } return; } - else - { - if(CheckAuthDone(Message, RealURI) == true) - { - std::string FinalFile = _config->FindDir("Dir::State::lists"); - FinalFile += URItoFileName(RealURI); - TransactionManager->TransactionStageCopy(this, MetaIndexFileSignature, FinalFile); - } - } + else if(CheckAuthDone(Message) == true) + TransactionManager->TransactionStageCopy(this, MetaIndexFileSignature, GetFinalFilename()); } /*}}}*/ void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)/*{{{*/ @@ -1692,14 +1682,14 @@ void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)/*{{{*/ Item::Failed(Message,Cnf); // check if we need to fail at this point - if (AuthPass == true && CheckStopAuthentication(RealURI, Message)) + if (AuthPass == true && CheckStopAuthentication(Message)) return; // FIXME: meh, this is not really elegant - string const Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI); + string const Final = GetFinalFileNameFromURI(RealURI); string const InReleaseURI = RealURI.replace(RealURI.rfind("Release.gpg"), 12, "InRelease"); - string const FinalInRelease = _config->FindDir("Dir::State::lists") + URItoFileName(InReleaseURI); + string const FinalInRelease = GetFinalFileNameFromURI(InReleaseURI); if (RealFileExists(Final) || RealFileExists(FinalInRelease)) { @@ -1739,7 +1729,7 @@ void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)/*{{{*/ // we parse the indexes here because at this point the user wanted // a repository that may potentially harm him MetaIndexParser->Load(MetaIndexFile); - if (!VerifyVendor(Message, RealURI)) + if (!VerifyVendor(Message)) /* expired Release files are still a problem you need extra force for */; else QueueIndexes(true); @@ -1760,9 +1750,9 @@ pkgAcqMetaIndex::pkgAcqMetaIndex(pkgAcquire *Owner, /*{{{*/ string MetaIndexSigURI,string MetaIndexSigURIDesc, string MetaIndexSigShortDesc, const vector* IndexTargets, indexRecords* MetaIndexParser) : - pkgAcqMetaBase(Owner, IndexTargets, MetaIndexParser, HashStringList(), + pkgAcqMetaBase(Owner, IndexTargets, MetaIndexParser, URI, HashStringList(), TransactionManager), - RealURI(URI), URIDesc(URIDesc), ShortDesc(ShortDesc), + URIDesc(URIDesc), ShortDesc(ShortDesc), MetaIndexSigURI(MetaIndexSigURI), MetaIndexSigURIDesc(MetaIndexSigURIDesc), MetaIndexSigShortDesc(MetaIndexSigShortDesc) { @@ -1796,24 +1786,13 @@ void pkgAcqMetaIndex::Init(std::string URIDesc, std::string ShortDesc) QueueURI(Desc); } /*}}}*/ -// pkgAcqMetaIndex::Custom600Headers - Insert custom request headers /*{{{*/ -// --------------------------------------------------------------------- -#if APT_PKG_ABI >= 413 -string pkgAcqMetaIndex::Custom600Headers() const -#else -string pkgAcqMetaIndex::Custom600Headers() -#endif -{ - return GetCustom600Headers(RealURI); -} - /*}}}*/ void pkgAcqMetaIndex::Done(string Message,unsigned long long Size, /*{{{*/ HashStringList const &Hashes, pkgAcquire::MethodConfig *Cfg) { Item::Done(Message,Size,Hashes,Cfg); - if(CheckDownloadDone(Message, RealURI)) + if(CheckDownloadDone(Message)) { // we have a Release file, now download the Signature, all further // verify/queue for additional downloads will be done in the @@ -1824,13 +1803,11 @@ void pkgAcqMetaIndex::Done(string Message,unsigned long long Size, /*{{{*/ MetaIndexSigShortDesc, MetaIndexFile, IndexTargets, MetaIndexParser); - string FinalFile = _config->FindDir("Dir::State::lists"); - FinalFile += URItoFileName(RealURI); - TransactionManager->TransactionStageCopy(this, DestFile, FinalFile); + TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename()); } } /*}}}*/ -bool pkgAcqMetaBase::CheckAuthDone(string Message, const string &RealURI) /*{{{*/ +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 @@ -1844,7 +1821,7 @@ bool pkgAcqMetaBase::CheckAuthDone(string Message, const string &RealURI) /*{{{* return false; } - if (!VerifyVendor(Message, RealURI)) + if (!VerifyVendor(Message)) { Status = StatAuthError; return false; @@ -1866,9 +1843,13 @@ bool pkgAcqMetaBase::CheckAuthDone(string Message, const string &RealURI) /*{{{* return true; } /*}}}*/ -// pkgAcqMetaBase::GetCustom600Headers - Get header for AcqMetaBase /*{{{*/ +// pkgAcqMetaBase::Custom600Headers - Get header for AcqMetaBase /*{{{*/ // --------------------------------------------------------------------- -string pkgAcqMetaBase::GetCustom600Headers(const string &RealURI) const +#if APT_PKG_ABI >= 413 +string pkgAcqMetaBase::Custom600Headers() const +#else +string pkgAcqMetaBase::Custom600Headers() +#endif { std::string Header = "\nIndex-File: true"; std::string MaximumSize; @@ -1876,8 +1857,7 @@ string pkgAcqMetaBase::GetCustom600Headers(const string &RealURI) const _config->FindI("Acquire::MaxReleaseFileSize", 10*1000*1000)); Header += MaximumSize; - string FinalFile = _config->FindDir("Dir::State::lists"); - FinalFile += URItoFileName(RealURI); + string const FinalFile = GetFinalFilename(); struct stat Buf; if (stat(FinalFile.c_str(),&Buf) == 0) @@ -1886,6 +1866,12 @@ string pkgAcqMetaBase::GetCustom600Headers(const string &RealURI) const return Header; } /*}}}*/ +// pkgAcqMetaBase::GetFinalFilename - Return the full final file path /*{{{*/ +std::string pkgAcqMetaBase::GetFinalFilename() const +{ + return GetFinalFileNameFromURI(RealURI); +} + /*}}}*/ // pkgAcqMetaBase::QueueForSignatureVerify /*{{{*/ void pkgAcqMetaBase::QueueForSignatureVerify(const std::string &MetaIndexFile, const std::string &MetaIndexFileSignature) @@ -1898,8 +1884,7 @@ void pkgAcqMetaBase::QueueForSignatureVerify(const std::string &MetaIndexFile, } /*}}}*/ // pkgAcqMetaBase::CheckDownloadDone /*{{{*/ -bool pkgAcqMetaBase::CheckDownloadDone(const std::string &Message, - const std::string &RealURI) +bool pkgAcqMetaBase::CheckDownloadDone(const std::string &Message) { // We have just finished downloading a Release file (it is not // verified yet) @@ -1923,11 +1908,7 @@ 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) - { - string FinalFile = _config->FindDir("Dir::State::lists"); - FinalFile += URItoFileName(RealURI); - DestFile = FinalFile; - } + DestFile = GetFinalFilename(); // set Item to complete as the remaining work is all local (verify etc) Complete = true; @@ -1993,7 +1974,7 @@ void pkgAcqMetaBase::QueueIndexes(bool verify) /*{{{*/ } } /*}}}*/ -bool pkgAcqMetaBase::VerifyVendor(string Message, const string &RealURI)/*{{{*/ +bool pkgAcqMetaBase::VerifyVendor(string Message) /*{{{*/ { string::size_type pos; @@ -2083,8 +2064,6 @@ void pkgAcqMetaIndex::Failed(string Message, pkgAcquire::Item::Failed(Message, Cnf); Status = StatDone; - string FinalFile = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI); - _error->Warning(_("The repository '%s' does not have a Release file. " "This is deprecated, please contact the owner of the " "repository."), URIDesc.c_str()); @@ -2096,7 +2075,7 @@ void pkgAcqMetaIndex::Failed(string Message, { // Done, queue for rename on transaction finished if (FileExists(DestFile)) - TransactionManager->TransactionStageCopy(this, DestFile, FinalFile); + TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename()); // queue without any kind of hashsum support QueueIndexes(false); @@ -2132,19 +2111,18 @@ pkgAcqMetaClearSig::~pkgAcqMetaClearSig() /*{{{*/ } /*}}}*/ // pkgAcqMetaClearSig::Custom600Headers - Insert custom request headers /*{{{*/ -// --------------------------------------------------------------------- #if APT_PKG_ABI >= 413 string pkgAcqMetaClearSig::Custom600Headers() const #else string pkgAcqMetaClearSig::Custom600Headers() #endif { - string Header = GetCustom600Headers(RealURI); + string Header = pkgAcqMetaBase::Custom600Headers(); Header += "\nFail-Ignore: true"; return Header; } /*}}}*/ -// pkgAcqMetaClearSig::Done - We got a file /*{{{*/ +// pkgAcqMetaClearSig::Done - We got a file /*{{{*/ // --------------------------------------------------------------------- void pkgAcqMetaClearSig::Done(std::string Message,unsigned long long Size, HashStringList const &Hashes, @@ -2165,21 +2143,12 @@ void pkgAcqMetaClearSig::Done(std::string Message,unsigned long long Size, if(AuthPass == false) { - if(CheckDownloadDone(Message, RealURI) == true) + if(CheckDownloadDone(Message) == true) QueueForSignatureVerify(DestFile, DestFile); return; } - else - { - if(CheckAuthDone(Message, RealURI) == true) - { - string FinalFile = _config->FindDir("Dir::State::lists"); - FinalFile += URItoFileName(RealURI); - - // queue for copy in place - TransactionManager->TransactionStageCopy(this, DestFile, FinalFile); - } - } + else if(CheckAuthDone(Message) == true) + TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename()); } /*}}}*/ void pkgAcqMetaClearSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /*{{{*/ @@ -2194,9 +2163,7 @@ void pkgAcqMetaClearSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /* // 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) - string FinalFile = _config->FindDir("Dir::State::lists"); - FinalFile.append(URItoFileName(RealURI)); - TransactionManager->TransactionStageRemoval(this, FinalFile); + TransactionManager->TransactionStageRemoval(this, GetFinalFilename()); Status = StatDone; new pkgAcqMetaIndex(Owner, TransactionManager, @@ -2206,7 +2173,7 @@ void pkgAcqMetaClearSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /* } else { - if(CheckStopAuthentication(RealURI, Message)) + if(CheckStopAuthentication(Message)) return; _error->Warning(_("The data from '%s' is not signed. Packages " @@ -2224,8 +2191,7 @@ void pkgAcqMetaClearSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /* * that PackageFile objects are correctly filled in */ if (FileExists(DestFile)) { - string FinalFile = _config->FindDir("Dir::State::lists"); - FinalFile += URItoFileName(RealURI); + string FinalFile = GetFinalFilename(); /* InRelease files become Release files, otherwise * they would be considered as trusted later on */ RealURI = RealURI.replace(RealURI.rfind("InRelease"), 9, @@ -2482,13 +2448,18 @@ void pkgAcqArchive::Done(string Message,unsigned long long Size, HashStringList } // Done, move it into position - string FinalFile = _config->FindDir("Dir::Cache::Archives"); - FinalFile += flNotDir(StoreFilename); + string const FinalFile = GetFinalFilename(); Rename(DestFile,FinalFile); StoreFilename = DestFile = FinalFile; 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 */ diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index 1af737e00..c2759b792 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -93,6 +93,9 @@ class pkgAcquire::Item : public WeakPointable */ 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. */ @@ -390,7 +393,13 @@ class pkgAcqMetaBase : public pkgAcquire::Item /*{{{*/ bool AuthPass; // required to deal gracefully with problems caused by incorrect ims hits - bool IMSHit; + 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. + */ + std::string RealURI; /** \brief Starts downloading the individual index files. * @@ -411,15 +420,17 @@ class pkgAcqMetaBase : public pkgAcquire::Item /*{{{*/ * \param Message The message block received from the fetch * subprocess. */ - bool CheckDownloadDone(const std::string &Message, - const std::string &RealURI); + bool CheckDownloadDone(const std::string &Message); /** \brief Queue the downloaded Signature for verification */ void QueueForSignatureVerify(const std::string &MetaIndexFile, const std::string &MetaIndexFileSignature); - /** \brief get the custom600 header for all pkgAcqMeta */ - std::string GetCustom600Headers(const std::string &RealURI) const; +#if APT_PKG_ABI >= 413 + virtual std::string Custom600Headers() const; +#else + virtual std::string Custom600Headers(); +#endif /** \brief Called when authentication succeeded. * @@ -430,20 +441,24 @@ class pkgAcqMetaBase : public pkgAcquire::Item /*{{{*/ * \param Message The message block received from the fetch * subprocess. */ - bool CheckAuthDone(std::string Message, const std::string &RealURI); + bool CheckAuthDone(std::string Message); /** Check if the current item should fail at this point */ - bool CheckStopAuthentication(const std::string &RealURI, - const std::string &Message); + bool CheckStopAuthentication(const std::string &Message); /** \brief Check that the release file is a release file for the * correct distribution. * * \return \b true if no fatal errors were encountered. */ - bool VerifyVendor(std::string Message, const std::string &RealURI); - + bool VerifyVendor(std::string Message); + + /** \brief Get the full pathname of the final file for the current URI */ + virtual std::string GetFinalFilename() const; + public: + virtual std::string DescURI() {return RealURI; }; + // transaction code void Add(Item *I); void AbortTransaction(); @@ -462,11 +477,12 @@ class pkgAcqMetaBase : public pkgAcquire::Item /*{{{*/ pkgAcqMetaBase(pkgAcquire *Owner, const std::vector* IndexTargets, 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) {}; + AuthPass(false), IMSHit(false), RealURI(RealURI) {}; }; /*}}}*/ /** \brief An acquire item that downloads the detached signature {{{ @@ -483,12 +499,6 @@ class APT_HIDDEN pkgAcqMetaSig : public pkgAcqMetaBase protected: - /** \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 The file we need to verify */ std::string MetaIndexFile; @@ -502,18 +512,12 @@ class APT_HIDDEN pkgAcqMetaSig : public pkgAcqMetaBase std::string ShortDesc; 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 RealURI; }; /** \brief Create a new pkgAcqMetaSig. */ pkgAcqMetaSig(pkgAcquire *Owner, @@ -540,11 +544,6 @@ class APT_HIDDEN pkgAcqMetaIndex : public pkgAcqMetaBase void *d; protected: - /** \brief The URI that is actually being downloaded; never - * modified by pkgAcqMetaIndex. - */ - std::string RealURI; - std::string URIDesc; std::string ShortDesc; @@ -566,12 +565,6 @@ class APT_HIDDEN pkgAcqMetaIndex : public pkgAcqMetaBase 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 RealURI; }; virtual void Finished(); /** \brief Create a new pkgAcqMetaIndex. */ @@ -652,6 +645,9 @@ class pkgAcqBaseIndex : public pkgAcquire::Item bool VerifyHashByMetaKey(HashStringList const &Hashes); + /** \brief Get the full pathname of the final file for the current URI */ + virtual std::string GetFinalFilename() const; + pkgAcqBaseIndex(pkgAcquire *Owner, pkgAcqMetaBase *TransactionManager, struct IndexTarget const * const Target, @@ -692,6 +688,9 @@ class APT_HIDDEN pkgAcqDiffIndex : public pkgAcqBaseIndex */ bool PackagesFileReadyInPartial; + /** \brief Get the full pathname of the final file for the current URI */ + virtual std::string GetFinalFilename() const; + public: // Specialized action members virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); @@ -999,16 +998,15 @@ class APT_HIDDEN pkgAcqIndex : public pkgAcqBaseIndex /** \brief Auto select the right compression to use */ void AutoSelectCompression(); - /** \brief Get the full pathname of the final file for the current URI - */ - std::string GetFinalFilename() const; - /** \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; + public: // Specialized action members @@ -1133,9 +1131,12 @@ class pkgAcqArchive : public pkgAcquire::Item /** \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; + 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); -- cgit v1.2.3 From ba6b79bd0090077724fa1272ea4d3a31706fcd5a Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 12 Apr 2015 17:08:46 +0200 Subject: 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). --- apt-pkg/acquire-item.cc | 90 ++++++++++++++++++++++++++++++++++++++++--------- apt-pkg/acquire-item.h | 28 ++++++++------- apt-pkg/acquire.h | 1 + 3 files changed, 91 insertions(+), 28 deletions(-) (limited to 'apt-pkg') 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; } @@ -1096,6 +1132,17 @@ void pkgAcqIndexMergeDiffs::Done(string Message,unsigned long long Size,HashStri if(Debug) std::clog << "allDone: " << DestFile << "\n" << std::endl; } +} + /*}}}*/ +// 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 /*{{{*/ @@ -1489,6 +1536,19 @@ void pkgAcqIndex::StageDecompressDone(string Message, TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename()); return; +} + /*}}}*/ +// AcqMetaBase - Constructor /*{{{*/ +pkgAcqMetaBase::pkgAcqMetaBase(pkgAcquire *Owner, + const std::vector* 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 /*{{{*/ @@ -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) ? "" : 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 @@ -73,11 +73,16 @@ class pkgAcquire::Item : public WeakPointable 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 */ - 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::iterator ItemIterator; -- cgit v1.2.3 From f4c7a238f4c29ac9b1e1172f103ab7dec5c5807d Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 16 Apr 2015 11:01:37 +0200 Subject: hide first pdiff merge failure debug message The sibling of this message are all guarded as debug messages, just this one had it missing an subsequently causes display issues if triggered. Git-Dch: Ignore --- apt-pkg/acquire-item.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 750e7daca..00862fe23 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -1044,7 +1044,8 @@ void pkgAcqIndexMergeDiffs::Failed(string Message,pkgAcquire::MethodConfig * Cnf // first failure means we should fallback State = StateErrorDiff; - std::clog << "Falling back to normal index file acquire" << std::endl; + if (Debug) + std::clog << "Falling back to normal index file acquire" << std::endl; new pkgAcqIndex(Owner, TransactionManager, Target, ExpectedHashes, MetaIndexParser); } /*}}}*/ -- cgit v1.2.3 From 6c9937da76b9155d166092b9dda22d06200510c1 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 22 Apr 2015 12:06:40 +0200 Subject: remove "first package seen is native package" assumption The fix for #777760 causes packages of foreign (and the native) architectures, to be created correctly, but invalidates (like the previously existing, but policy-forbidden architecture-less packages we had to support for some upgrade scenarios) the assumption that the first (and only) package in the cache for a single architecture system must be the package for the native architecture (as, where should the other architectures come from, right? Wrong.). Depending on the order of parsing sources more or less packages can be effected by this. The effects are strange (for apt it mostly effects simulation/debug output, but also apt-mark on these specific packages), which complicates debugging, but relatively harmless if understood as most actions do not need direct named access to packages. The problem is fixed by removing the single-arch special casing in the paths who had them (Cache.FindPkg), so they use the same code as multi-arch systems, which use them as a wrapper for Grp.FindPkg. Note that single-arch system code was using Grp.FindPkg before as well if a Grp structure was handily available, so we don't introduce new untested code here: We remove more brittle special cases which are less tested instead (this was planed to be done for Stretch anyhow). Note further that the method with the assumption itself isn't fixed. As it is a private method I opted for declaring it deprecated instead and remove all its call positions. As it is private no-one can call this method legally (thanks to how c++ works by default its still an exported symbol through) and fixing it basically means reimplementing code we already have in Grp.FindPkg. Removing rather than fixing seems hence like a good solution. Closes: 782777 Thanks: Axel Beckert for testing --- apt-pkg/pkgcache.cc | 14 +------------- apt-pkg/pkgcache.h | 2 +- 2 files changed, 2 insertions(+), 14 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index d7c9656b9..a7b75dae8 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -230,12 +230,7 @@ pkgCache::PkgIterator pkgCache::SingleArchFindPkg(const string &Name) pkgCache::PkgIterator pkgCache::FindPkg(const string &Name) { size_t const found = Name.find(':'); if (found == string::npos) - { - if (MultiArchCache() == false) - return SingleArchFindPkg(Name); - else - return FindPkg(Name, "native"); - } + return FindPkg(Name, "native"); string const Arch = Name.substr(found+1); /* Beware: This is specialcased to handle pkg:any in dependencies as these are linked to virtual pkg:any named packages with all archs. @@ -249,13 +244,6 @@ pkgCache::PkgIterator pkgCache::FindPkg(const string &Name) { // --------------------------------------------------------------------- /* Returns 0 on error, pointer to the package otherwise */ pkgCache::PkgIterator pkgCache::FindPkg(const string &Name, string const &Arch) { - if (MultiArchCache() == false && Arch != "none") { - if (Arch == "native" || Arch == "all" || Arch == "any" || - Arch == NativeArch()) - return SingleArchFindPkg(Name); - else - return PkgIterator(*this,0); - } /* We make a detour via the GrpIterator here as on a multi-arch environment a group is easier to find than a package (less entries in the buckets) */ diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h index 5e8a9630a..a7e520bc9 100644 --- a/apt-pkg/pkgcache.h +++ b/apt-pkg/pkgcache.h @@ -218,7 +218,7 @@ class pkgCache /*{{{*/ private: bool MultiArchEnabled; - PkgIterator SingleArchFindPkg(const std::string &Name); + APT_DEPRECATED PkgIterator SingleArchFindPkg(const std::string &Name); }; /*}}}*/ // Header structure /*{{{*/ -- cgit v1.2.3 From 15901516326737a67f2a9af26cd7e434162de019 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 28 Apr 2015 17:55:00 +0200 Subject: Move sysconf(_SC_OPEN_MAX); out of the for() loop to avoid unneeded syscalls --- apt-pkg/contrib/fileutl.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 1ba4674e5..1e6d96fe9 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -778,8 +778,9 @@ pid_t ExecFork(std::set 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 != sysconf(_SC_OPEN_MAX); K++) + for (int K = 3; K != ScOpenMax; K++) { if(KeepFDs.find(K) == KeepFDs.end()) fcntl(K,F_SETFD,FD_CLOEXEC); -- cgit v1.2.3 From 146f7715a9f36d246b461255b3c683b479296915 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 27 Apr 2015 10:59:27 +0200 Subject: improve partial/ cleanup in abort and failure cases Especially pdiff-enhanced downloads have the tendency to fail for various reasons from which we can recover and even a successful download used to leave the old unpatched index in partial/. By adding a new method responsible for making the transaction of an individual file happen we can at specialisations especially for abort cases to deal with the cleanup. This also helps in keeping the compressed indexes around if another index failed instead of keeping the decompressed files, which we wouldn't pick up in the next call. --- apt-pkg/acquire-item.cc | 193 ++++++++++++++++++++++++++++++++---------------- apt-pkg/acquire-item.h | 17 +++-- 2 files changed, 143 insertions(+), 67 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 00862fe23..01ce0e650 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -173,6 +173,39 @@ void pkgAcquire::Item::Failed(string Message,pkgAcquire::MethodConfig *Cnf) 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; +} + /*}}}*/ // Acquire::Item::Start - Item has begun to download /*{{{*/ // --------------------------------------------------------------------- /* Stash status and the file size. Note that setting Complete means @@ -300,6 +333,9 @@ bool pkgAcquire::Item::RenameOnError(pkgAcquire::Item::RenameOnErrorState const // the method is expected to report a good error for this Status = StatError; break; + case PDiffError: + // no handling here, done by callers + break; } return false; } @@ -374,7 +410,7 @@ pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner, HashStringList const &ExpectedHashes, indexRecords *MetaIndexParser) : pkgAcqBaseIndex(Owner, TransactionManager, Target, ExpectedHashes, - MetaIndexParser), PackagesFileReadyInPartial(false) + MetaIndexParser) { Debug = _config->FindB("Debug::pkgAcquire::Diffs",false); @@ -671,20 +707,6 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile) /*{{{*/ return false; } - // FIXME: make this use the method - PackagesFileReadyInPartial = true; - std::string const Partial = GetPartialFileNameFromURI(RealURI); - - FileFd From(CurrentPackagesFile, FileFd::ReadOnly); - FileFd To(Partial, FileFd::WriteEmpty); - if(CopyFile(From, To) == false) - return _error->Errno("CopyFile", "failed to copy"); - - if(Debug) - std::cerr << "Done copying " << CurrentPackagesFile - << " -> " << Partial - << std::endl; - // we have something, queue the diffs string::size_type const last_space = Description.rfind(" "); if(last_space != string::npos) @@ -738,6 +760,24 @@ void pkgAcqDiffIndex::Failed(string Message,pkgAcquire::MethodConfig * Cnf)/*{{{ 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; +} + /*}}}*/ void pkgAcqDiffIndex::Done(string Message,unsigned long long Size,HashStringList const &Hashes, /*{{{*/ pkgAcquire::MethodConfig *Cnf) { @@ -765,15 +805,21 @@ void pkgAcqDiffIndex::Done(string Message,unsigned long long Size,HashStringList if(StringToBool(LookupTag(Message,"IMS-Hit"),false)) DestFile = FinalFile; - if(!ParseDiffIndex(DestFile)) - return Failed("Message: Couldn't parse pdiff index", Cnf); + if(ParseDiffIndex(DestFile) == false) + { + Failed("Message: Couldn't parse pdiff index", Cnf); + // queue for final move - this should happen even if we fail + // while parsing (e.g. on sizelimit) and download the complete file. + TransactionManager->TransactionStageCopy(this, DestFile, FinalFile); + return; + } - // queue for final move TransactionManager->TransactionStageCopy(this, DestFile, FinalFile); Complete = true; Status = StatDone; Dequeue(); + return; } /*}}}*/ @@ -808,6 +854,17 @@ pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire *Owner, } else { + // patching needs to be bootstrapped with the 'old' version + std::string const PartialFile = GetPartialFileNameFromURI(RealURI); + if (RealFileExists(PartialFile) == false) + { + if (symlink(GetFinalFilename().c_str(), PartialFile.c_str()) != 0) + { + Failed("Link creation of " + PartialFile + " to " + GetFinalFilename() + " failed", NULL); + return; + } + } + // get the next diff State = StateFetchDiff; QueueNextDiff(); @@ -822,6 +879,8 @@ 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); + RenameOnError(PDiffError); new pkgAcqIndex(Owner, TransactionManager, Target, ExpectedHashes, MetaIndexParser); Finish(); } @@ -950,6 +1009,8 @@ void pkgAcqIndexDiffs::Done(string Message,unsigned long long Size, HashStringLi 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; } @@ -1046,6 +1107,8 @@ 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); + RenameOnError(PDiffError); new pkgAcqIndex(Owner, TransactionManager, Target, ExpectedHashes, MetaIndexParser); } /*}}}*/ @@ -1069,6 +1132,8 @@ void pkgAcqIndexMergeDiffs::Done(string Message,unsigned long long Size,HashStri 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; } @@ -1090,6 +1155,13 @@ void pkgAcqIndexMergeDiffs::Done(string Message,unsigned long long Size,HashStri // this is the last completed diff, so we are ready to apply now State = StateApplyDiff; + // patching needs to be bootstrapped with the 'old' version + if (symlink(GetFinalFilename().c_str(), FinalFile.c_str()) != 0) + { + Failed("Link creation of " + FinalFile + " to " + GetFinalFilename() + " failed", NULL); + return; + } + if(Debug) std::clog << "Sending to rred method: " << FinalFile << std::endl; @@ -1109,15 +1181,14 @@ void pkgAcqIndexMergeDiffs::Done(string Message,unsigned long long Size,HashStri return; } - // move the result into place - std::string const FinalFile = GetFinalFilename(); + std::string const Final = GetFinalFilename(); if(Debug) std::clog << "Queue patched file in place: " << std::endl - << DestFile << " -> " << FinalFile << std::endl; + << DestFile << " -> " << Final << std::endl; // queue for copy by the transaction manager - TransactionManager->TransactionStageCopy(this, DestFile, FinalFile); + TransactionManager->TransactionStageCopy(this, DestFile, Final); // ensure the ed's are gone regardless of list-cleanup for (std::vector::const_iterator I = allPatches->begin(); @@ -1127,6 +1198,7 @@ void pkgAcqIndexMergeDiffs::Done(string Message,unsigned long long Size,HashStri std::string patch = PartialFile + ".ed." + (*I)->patch.file + ".gz"; unlink(patch.c_str()); } + unlink(FinalFile.c_str()); // all set and done Complete = true; @@ -1337,12 +1409,6 @@ void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf) return; } - // on decompression failure, remove bad versions in partial/ - if (Stage == STAGE_DECOMPRESS_AND_VERIFY) - { - unlink(EraseFileName.c_str()); - } - Item::Failed(Message,Cnf); if(Target->IsOptional() && ExpectedHashes.empty() && Stage == STAGE_DOWNLOAD) @@ -1351,6 +1417,30 @@ void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf) 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 { @@ -1530,9 +1620,6 @@ void pkgAcqIndex::StageDecompressDone(string Message, return; } - // remove the compressed version of the file - unlink(EraseFileName.c_str()); - // Done, queue for rename on transaction finished TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename()); @@ -1568,14 +1655,7 @@ void pkgAcqMetaBase::AbortTransaction() for (std::vector::iterator I = Transaction.begin(); I != Transaction.end(); ++I) { - if(_config->FindB("Debug::Acquire::Transaction", false) == true) - std::clog << " Cancel: " << (*I)->DestFile << std::endl; - // the transaction will abort, so stop anything that is idle - if ((*I)->Status == pkgAcquire::Item::StatIdle) - { - (*I)->Status = pkgAcquire::Item::StatDone; - (*I)->Dequeue(); - } + (*I)->TransactionState(TransactionAbort); } Transaction.clear(); } @@ -1585,10 +1665,16 @@ bool pkgAcqMetaBase::TransactionHasError() { for (pkgAcquire::ItemIterator I = Transaction.begin(); I != Transaction.end(); ++I) - if((*I)->Status != pkgAcquire::Item::StatDone && - (*I)->Status != pkgAcquire::Item::StatIdle) - return true; - + { + 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; } /*}}}*/ @@ -1603,24 +1689,7 @@ void pkgAcqMetaBase::CommitTransaction() for (std::vector::iterator I = Transaction.begin(); I != Transaction.end(); ++I) { - if((*I)->PartialFile != "") - { - if(_config->FindB("Debug::Acquire::Transaction", false) == true) - std::clog << "mv " << (*I)->PartialFile << " -> "<< (*I)->DestFile << " " - << (*I)->DescURI() << std::endl; - - Rename((*I)->PartialFile, (*I)->DestFile); - } else { - if(_config->FindB("Debug::Acquire::Transaction", false) == true) - std::clog << "rm " - << (*I)->DestFile - << " " - << (*I)->DescURI() - << std::endl; - unlink((*I)->DestFile.c_str()); - } - // mark that this transaction is finished - (*I)->TransactionManager = 0; + (*I)->TransactionState(TransactionCommit); } Transaction.clear(); } @@ -1634,7 +1703,7 @@ void pkgAcqMetaBase::TransactionStageCopy(Item *I, I->DestFile = To; } /*}}}*/ -// AcqMetaBase::TransactionStageRemoval - Sage a file for removal /*{{{*/ +// AcqMetaBase::TransactionStageRemoval - Stage a file for removal /*{{{*/ void pkgAcqMetaBase::TransactionStageRemoval(Item *I, const std::string &FinalFile) { diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index 148728b3c..33a28671c 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -344,7 +344,8 @@ class pkgAcquire::Item : public WeakPointable InvalidFormat, SignatureError, NotClearsigned, - MaximumSizeExceeded + MaximumSizeExceeded, + PDiffError, }; /** \brief Rename failed file and set error @@ -353,6 +354,12 @@ class pkgAcquire::Item : public WeakPointable */ bool RenameOnError(RenameOnErrorState const state); + enum TransactionStates { + TransactionCommit, + TransactionAbort, + }; + virtual bool TransactionState(TransactionStates const state); + /** \brief The HashSums of the item is supposed to have than done */ HashStringList ExpectedHashes; @@ -685,14 +692,12 @@ class APT_HIDDEN pkgAcqDiffIndex : public pkgAcqBaseIndex */ std::string Description; - /** \brief If the copy step of the packages file is done - */ - bool PackagesFileReadyInPartial; - /** \brief Get the full pathname of the final file for the current URI */ virtual std::string GetFinalFilename() const; virtual bool QueueURI(pkgAcquire::ItemDesc &Item); + + virtual bool TransactionState(TransactionStates const state); public: // Specialized action members virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); @@ -1010,6 +1015,8 @@ class APT_HIDDEN pkgAcqIndex : public pkgAcqBaseIndex /** \brief Get the full pathname of the final file for the current URI */ virtual std::string GetFinalFilename() const; + virtual bool TransactionState(TransactionStates const state); + public: // Specialized action members virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); -- cgit v1.2.3 From 3f732aa6ad0a81b6a6942a61fd5ed26a26590e8e Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 28 Apr 2015 23:42:03 +0200 Subject: a pin of 1000 always means downgrade allowed The documentation says this, but the code only agreed while evaluating specific packages, but not generics. These needed a pin above 1000 to have the same effect. The code causing this makes references to a 'second pesduo status file', but nowhere is explained what this might stand for and/or what it was, so we do the only reasonable thing: Remove all references and do as documented. --- apt-pkg/policy.cc | 32 ++++++++++---------------------- 1 file changed, 10 insertions(+), 22 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/policy.cc b/apt-pkg/policy.cc index 3cfc32829..9a1d2977e 100644 --- a/apt-pkg/policy.cc +++ b/apt-pkg/policy.cc @@ -4,22 +4,12 @@ /* ###################################################################### Package Version Policy implementation - + This is just a really simple wrapper around pkgVersionMatch with some added goodies to manage the list of things.. - - Priority Table: - - 1000 -> inf = Downgradeable priorities - 1000 = The 'no downgrade' pseduo-status file - 100 -> 1000 = Standard priorities - 990 = Config file override package files - 989 = Start for preference auto-priorities - 500 = Default package files - 100 = The status file and ButAutomaticUpgrades sources - 0 -> 100 = NotAutomatic sources like experimental - -inf -> 0 = Never selected - + + See man apt_preferences for what value means what. + ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ @@ -56,7 +46,7 @@ using namespace std; file matches the V0 policy engine. */ pkgPolicy::pkgPolicy(pkgCache *Owner) : Pins(0), PFPriority(0), Cache(Owner) { - if (Owner == 0 || &(Owner->Head()) == 0) + if (Owner == 0) return; PFPriority = new signed short[Owner->Head().PackageFileCount]; Pins = new Pin[Owner->Head().PackageCount]; @@ -125,7 +115,7 @@ bool pkgPolicy::InitDefaults() else PFPriority[F->ID] = Cur; - if (PFPriority[F->ID] > 1000) + if (PFPriority[F->ID] >= 1000) StatusOverride = true; Fixed[F->ID] = true; @@ -166,9 +156,7 @@ pkgCache::VerIterator pkgPolicy::GetCandidateVer(pkgCache::PkgIterator const &Pk effectively excludes everything <= 0 which are the non-automatic priorities.. The status file is given a prio of 100 which will exclude not-automatic sources, except in a single shot not-installed mode. - The second pseduo-status file is at prio 1000, above which will permit - the user to force-downgrade things. - + The user pin is subject to the same priority rules as default selections. Thus there are two ways to create a pin - a pin that tracks the default when the default is taken away, and a permanent @@ -218,9 +206,9 @@ pkgCache::VerIterator pkgPolicy::GetCandidateVer(pkgCache::PkgIterator const &Pk Pref = Ver; PrefSeen = true; } - /* Elevate our current selection (or the status file itself) - to the Pseudo-status priority. */ - Max = 1000; + /* Elevate our current selection (or the status file itself) so that only + a downgrade can override it from now on */ + Max = 999; // Fast path optimize. if (StatusOverride == false) -- cgit v1.2.3 From ab640001ee772fa27ee789f6717805f9d46d5bce Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 28 Apr 2015 23:59:00 +0200 Subject: remove unused and strange default-value for pins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the pin for a generic pin is 0, it get a value by strange looking rules, if the pin is specific the rules are at least not strange, but the value 989 is a magic number without any direct meaning… but both never happens in practice as the parsing skips such entries with a warning, so there always is a priority != 0 and the code therefore never used. --- apt-pkg/policy.cc | 34 ++++++++++------------------------ 1 file changed, 10 insertions(+), 24 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/policy.cc b/apt-pkg/policy.cc index 9a1d2977e..00693ce54 100644 --- a/apt-pkg/policy.cc +++ b/apt-pkg/policy.cc @@ -97,37 +97,29 @@ bool pkgPolicy::InitDefaults() // Apply the defaults.. SPtrArray Fixed = new bool[Cache->HeaderP->PackageFileCount]; memset(Fixed,0,sizeof(*Fixed)*Cache->HeaderP->PackageFileCount); - signed Cur = 989; StatusOverride = false; - for (vector::const_iterator I = Defaults.begin(); I != Defaults.end(); - ++I, --Cur) + for (vector::const_iterator I = Defaults.begin(); I != Defaults.end(); ++I) { pkgVersionMatch Match(I->Data,I->Type); for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F != Cache->FileEnd(); ++F) { - if (Match.FileMatch(F) == true && Fixed[F->ID] == false) + if (Fixed[F->ID] == false && Match.FileMatch(F) == true) { - if (I->Priority != 0 && I->Priority > 0) - Cur = I->Priority; - - if (I->Priority < 0) - PFPriority[F->ID] = I->Priority; - else - PFPriority[F->ID] = Cur; - + PFPriority[F->ID] = I->Priority; + if (PFPriority[F->ID] >= 1000) StatusOverride = true; - + Fixed[F->ID] = true; - } - } + } + } } if (_config->FindB("Debug::pkgPolicy",false) == true) for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F != Cache->FileEnd(); ++F) - std::clog << "Prio of " << F.FileName() << ' ' << PFPriority[F->ID] << std::endl; - - return true; + std::clog << "Prio of " << F.FileName() << ' ' << PFPriority[F->ID] << std::endl; + + return true; } /*}}}*/ // Policy::GetCandidateVer - Get the candidate install version /*{{{*/ @@ -324,13 +316,7 @@ pkgCache::VerIterator pkgPolicy::GetMatch(pkgCache::PkgIterator const &Pkg) APT_PURE signed short pkgPolicy::GetPriority(pkgCache::PkgIterator const &Pkg) { if (Pins[Pkg->ID].Type != pkgVersionMatch::None) - { - // In this case 0 means default priority - if (Pins[Pkg->ID].Priority == 0) - return 989; return Pins[Pkg->ID].Priority; - } - return 0; } APT_PURE signed short pkgPolicy::GetPriority(pkgCache::PkgFileIterator const &File) -- cgit v1.2.3 From 98c9c26c123aa1ef6ad01b0bb60c782b920ce3b3 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 9 May 2015 12:39:22 +0200 Subject: show non-matching m-a:same versions in debug message Slightly rewriting the code to ensure we only use two sources for the versions as it could otherwise be confusing to look at. --- apt-pkg/depcache.cc | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 25c945ebb..73c5bb320 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -1315,14 +1315,18 @@ bool pkgDepCache::IsInstallOkMultiArchSameVersionSynced(PkgIterator const &Pkg, GrpIterator const Grp = Pkg.Group(); for (PkgIterator P = Grp.PackageList(); P.end() == false; P = Grp.NextPkg(P)) { - // not installed or version synced: fine by definition + // not installed or self-check: fine by definition + if (P->CurrentVer == 0 || P == Pkg) + continue; + + // not having a candidate or being in sync // (simple string-compare as stuff like '1' == '0:1-0' can't happen here) - if (P->CurrentVer == 0 || strcmp(Pkg.CandVersion(), P.CandVersion()) == 0) + VerIterator CV = PkgState[P->ID].CandidateVerIter(*this); + if (CV.end() == true || strcmp(Pkg.CandVersion(), CV.VerStr()) == 0) continue; + // packages losing M-A:same can be out-of-sync - VerIterator CV = PkgState[P->ID].CandidateVerIter(*this); - if (unlikely(CV.end() == true) || - (CV->MultiArch & pkgCache::Version::Same) != pkgCache::Version::Same) + if ((CV->MultiArch & pkgCache::Version::Same) != pkgCache::Version::Same) continue; // not downloadable means the package is obsolete, so allow out-of-sync @@ -1332,7 +1336,8 @@ bool pkgDepCache::IsInstallOkMultiArchSameVersionSynced(PkgIterator const &Pkg, PkgState[Pkg->ID].iFlags |= AutoKept; if (unlikely(DebugMarker == true)) std::clog << OutputInDepth(Depth) << "Ignore MarkInstall of " << Pkg - << " as its M-A:same siblings are not version-synced" << std::endl; + << " as it is not in sync with its M-A:same sibling " << P + << " (" << Pkg.CandVersion() << " != " << CV.VerStr() << ")" << std::endl; return false; } -- cgit v1.2.3 From ad5a4ac2bccb04f4aa74aeb2cefa90c79ed4b5e9 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 9 May 2015 14:02:59 +0200 Subject: fix macro definition for very old GCC < 3 Git-Dch: Ignore --- apt-pkg/contrib/macros.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/macros.h b/apt-pkg/contrib/macros.h index 14541d4d8..2f9c6c269 100644 --- a/apt-pkg/contrib/macros.h +++ b/apt-pkg/contrib/macros.h @@ -89,7 +89,7 @@ #define APT_MUSTCHECK __attribute__((warn_unused_result)) #else #define APT_NONNULL(...) - #define APT_REQRET + #define APT_MUSTCHECK #endif #if APT_GCC_VERSION >= 0x0400 -- cgit v1.2.3 From e8fb1cdfdd13e45f2b3abbd57a28b57ae6137f14 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 9 May 2015 18:55:41 +0200 Subject: sync TFRewrite*Order arrays with dpkg and dak dpkg and dak know various field names and order them in their output, while we have yet another order and have to play catch up with them as we are sitting between chairs here and neither order is ideal for us, too. A little testcase is from now on supposed to help ensureing that we do not derivate to far away from which fields dpkg knows and orders. --- apt-pkg/tagfile-order.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++ apt-pkg/tagfile.cc | 63 ++-------------------------- 2 files changed, 112 insertions(+), 60 deletions(-) create mode 100644 apt-pkg/tagfile-order.c (limited to 'apt-pkg') diff --git a/apt-pkg/tagfile-order.c b/apt-pkg/tagfile-order.c new file mode 100644 index 000000000..10c61ab94 --- /dev/null +++ b/apt-pkg/tagfile-order.c @@ -0,0 +1,109 @@ +/* In this file is the order defined in which e.g. apt-ftparchive will write stanzas in. + Other commands might or might not use this. 'apt-cache show' e.g. does NOT! + + The order we chose here is inspired by both dpkg and dak. + The testcase test/integration/test-apt-tagfile-fields-order intends to ensure that + this file isn't lacking (too far) behind dpkg over time. */ + +static const char *iTFRewritePackageOrder[] = { + "Package", + "Package-Type", + "Architecture", + "Subarchitecture", // Used only by d-i + "Version", + "Revision", // Obsolete (warning in dpkg) + "Package-Revision", // Obsolete (warning in dpkg) + "Package_Revision", // Obsolete (warning in dpkg) + "Kernel-Version", // Used only by d-i + "Built-Using", + "Built-For-Profiles", + "Multi-Arch", + "Status", + "Priority", + "Class", // dpkg nickname for Priority + "Essential", + "Installer-Menu-Item", // Used only by d-i + "Section", + "Source", + "Origin", + "Maintainer", + "Original-Maintainer", // unknown in dpkg order + "Bugs", + "Config-Version", // Internal of dpkg + "Conffiles", + "Triggers-Awaited", + "Triggers-Pending", + "Installed-Size", + "Provides", + "Pre-Depends", + "Depends", + "Recommends", + "Recommended", // dpkg nickname for Recommends + "Suggests", + "Optional", // dpkg nickname for Suggests + "Conflicts", + "Breaks", + "Replaces", + "Enhances", + "Filename", + "MSDOS-Filename", // Obsolete (used by dselect) + "Size", + "MD5sum", + "SHA1", + "SHA256", + "SHA512", + "Homepage", + "Description", + "Tag", + "Task", + 0 +}; +static const char *iTFRewriteSourceOrder[] = { + "Package", + "Source", // dsc file, renamed to Package in Sources + "Format", + "Binary", + "Architecture", + "Version", + "Priority", + "Class", // dpkg nickname for Priority + "Section", + "Origin", + "Maintainer", + "Original-Maintainer", // unknown in dpkg order + "Uploaders", + "Dm-Upload-Allowed", // Obsolete (ignored by dak) + "Standards-Version", + "Build-Depends", + "Build-Depends-Arch", + "Build-Depends-Indep", + "Build-Conflicts", + "Build-Conflicts-Arch", + "Build-Conflicts-Indep", + "Testsuite", + "Homepage", + "Vcs-Browser", + "Vcs-Browse", // dak only (nickname?) + "Vcs-Arch", + "Vcs-Bzr", + "Vcs-Cvs", + "Vcs-Darcs", + "Vcs-Git", + "Vcs-Hg", + "Vcs-Mtn", + "Vcs-Svn", + "Directory", + "Package-List", + "Files", + "Checksums-Md5", + "Checksums-Sha1", + "Checksums-Sha256", + "Checksums-Sha512", + 0 +}; + +/* Two levels of initialization are used because gcc will set the symbol + size of an array to the length of the array, causing dynamic relinking + errors. Doing this makes the symbol size constant */ +const char **TFRewritePackageOrder = iTFRewritePackageOrder; +const char **TFRewriteSourceOrder = iTFRewriteSourceOrder; diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc index 9c40c8c92..2f7900d93 100644 --- a/apt-pkg/tagfile.cc +++ b/apt-pkg/tagfile.cc @@ -623,71 +623,14 @@ APT_PURE unsigned int pkgTagSection::Count() const { /*{{{*/ return d->Tags.size() - 1; } /*}}}*/ + +#include "tagfile-order.c" + // TFRewrite - Rewrite a control record /*{{{*/ // --------------------------------------------------------------------- /* This writes the control record to stdout rewriting it as necessary. The override map item specificies the rewriting rules to follow. This also takes the time to sort the feild list. */ - -/* The order of this list is taken from dpkg source lib/parse.c the fieldinfos - array. */ -static const char *iTFRewritePackageOrder[] = { - "Package", - "Essential", - "Status", - "Priority", - "Section", - "Installed-Size", - "Maintainer", - "Original-Maintainer", - "Architecture", - "Source", - "Version", - "Revision", // Obsolete - "Config-Version", // Obsolete - "Replaces", - "Provides", - "Depends", - "Pre-Depends", - "Recommends", - "Suggests", - "Conflicts", - "Breaks", - "Conffiles", - "Filename", - "Size", - "MD5sum", - "SHA1", - "SHA256", - "SHA512", - "MSDOS-Filename", // Obsolete - "Description", - 0}; -static const char *iTFRewriteSourceOrder[] = {"Package", - "Source", - "Binary", - "Version", - "Priority", - "Section", - "Maintainer", - "Original-Maintainer", - "Build-Depends", - "Build-Depends-Indep", - "Build-Conflicts", - "Build-Conflicts-Indep", - "Architecture", - "Standards-Version", - "Format", - "Directory", - "Files", - 0}; - -/* Two levels of initialization are used because gcc will set the symbol - size of an array to the length of the array, causing dynamic relinking - errors. Doing this makes the symbol size constant */ -const char **TFRewritePackageOrder = iTFRewritePackageOrder; -const char **TFRewriteSourceOrder = iTFRewriteSourceOrder; - bool TFRewrite(FILE *Output,pkgTagSection const &Tags,const char *Order[], TFRewriteData *Rewrite) { -- cgit v1.2.3 From d38926efe1e6d2511bd852607ff4f9c8b60dc76c Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 9 May 2015 15:37:23 +0200 Subject: stop depending on copy-on-write for std::string In 66c3875df391b1120b43831efcbe88a78569fbfe we workaround/fixed a problem where the code makes the assumption that the compiler uses copy-on-write implementations for std::string. Turns out that for c++11 compatibility gcc >= 5 will stop doing this by default. --- apt-pkg/deb/debindexfile.cc | 24 ++++++++++++------------ apt-pkg/deb/debindexfile.h | 18 +++++++++--------- 2 files changed, 21 insertions(+), 21 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index 49c6e8cc0..d672b4fd8 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -413,8 +413,8 @@ pkgCache::PkgFileIterator debPackagesIndex::FindInCache(pkgCache &Cache) const // TranslationsIndex::debTranslationsIndex - Contructor /*{{{*/ // --------------------------------------------------------------------- /* */ -debTranslationsIndex::debTranslationsIndex(string URI,string Dist,string Section, - char const * const Translation) : +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) {} @@ -458,13 +458,13 @@ string debTranslationsIndex::IndexURI(const char *Type) const /* 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 -{ - char S[300]; +{ + std::string S; if (Short == true) - snprintf(S,sizeof(S),"%s",Info(TranslationFile().c_str()).c_str()); + strprintf(S,"%s",Info(TranslationFile().c_str()).c_str()); else - snprintf(S,sizeof(S),"%s (%s)",Info(TranslationFile().c_str()).c_str(), - IndexFile(Language).c_str()); + strprintf(S,"%s (%s)",Info(TranslationFile().c_str()).c_str(), + IndexFile(Language.c_str()).c_str()); return S; } /*}}}*/ @@ -488,7 +488,7 @@ string debTranslationsIndex::Info(const char *Type) const /*}}}*/ bool debTranslationsIndex::HasPackages() const /*{{{*/ { - return FileExists(IndexFile(Language)); + return FileExists(IndexFile(Language.c_str())); } /*}}}*/ // TranslationsIndex::Exists - Check if the index is available /*{{{*/ @@ -496,7 +496,7 @@ bool debTranslationsIndex::HasPackages() const /*{{{*/ /* */ bool debTranslationsIndex::Exists() const { - return FileExists(IndexFile(Language)); + return FileExists(IndexFile(Language.c_str())); } /*}}}*/ // TranslationsIndex::Size - Return the size of the index /*{{{*/ @@ -509,7 +509,7 @@ unsigned long debTranslationsIndex::Size() const /* we need to ignore errors here; if the lists are absent, just return 0 */ _error->PushToStack(); - FileFd f(IndexFile(Language), FileFd::ReadOnly, FileFd::Extension); + FileFd f(IndexFile(Language.c_str()), FileFd::ReadOnly, FileFd::Extension); if (!f.Failed()) size = f.Size(); @@ -526,7 +526,7 @@ unsigned long debTranslationsIndex::Size() const bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const { // Check the translation file, if in use - string TranslationFile = IndexFile(Language); + string TranslationFile = IndexFile(Language.c_str()); if (FileExists(TranslationFile)) { FileFd Trans(TranslationFile,FileFd::ReadOnly, FileFd::Extension); @@ -556,7 +556,7 @@ bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const /* */ pkgCache::PkgFileIterator debTranslationsIndex::FindInCache(pkgCache &Cache) const { - string FileName = IndexFile(Language); + string FileName = IndexFile(Language.c_str()); pkgCache::PkgFileIterator File = Cache.FileBegin(); for (; File.end() == false; ++File) diff --git a/apt-pkg/deb/debindexfile.h b/apt-pkg/deb/debindexfile.h index 81914f203..1e5882071 100644 --- a/apt-pkg/deb/debindexfile.h +++ b/apt-pkg/deb/debindexfile.h @@ -97,11 +97,11 @@ class APT_HIDDEN debTranslationsIndex : public pkgIndexFile /** \brief dpointer placeholder (for later in case we need it) */ void *d; - std::string URI; - std::string Dist; - std::string Section; - const char * const Language; - + std::string const URI; + std::string const Dist; + std::string const Section; + std::string const Language; + 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; @@ -109,12 +109,12 @@ class APT_HIDDEN debTranslationsIndex : public pkgIndexFile 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 std::string Describe(bool Short) const; + // Interface for the Cache Generator virtual bool Exists() const; virtual bool HasPackages() const; @@ -122,7 +122,7 @@ class APT_HIDDEN debTranslationsIndex : public pkgIndexFile virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const; virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const; - debTranslationsIndex(std::string URI,std::string Dist,std::string Section, char const * const Language); + debTranslationsIndex(std::string const &URI,std::string const &Dist,std::string const &Section, std::string const &Language); virtual ~debTranslationsIndex(); }; -- cgit v1.2.3 From 8d058ea53b18348f81229049a27d14282bd8d8c1 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 10 May 2015 22:53:15 +0200 Subject: implement a more c++-style TFRewrite alternative TFRewrite is okay, but it has obscure limitations (256 Tags), even more obscure bugs (order for renames is defined by the old name) and the interface is very c-style encouraging bad usage like we do it in apt-ftparchive passing massive amounts of c_str() from std::string in. The old-style is marked as deprecated accordingly. The next commit will fix all places in the apt code to not use the old-style anymore. --- apt-pkg/tagfile.cc | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++- apt-pkg/tagfile.h | 47 ++++++++++++----- 2 files changed, 181 insertions(+), 14 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc index 2f7900d93..5ff495fbd 100644 --- a/apt-pkg/tagfile.cc +++ b/apt-pkg/tagfile.cc @@ -509,8 +509,6 @@ bool pkgTagSection::Find(const char *Tag,const char *&Start, } /*}}}*/ // TagSection::FindS - Find a string /*{{{*/ -// --------------------------------------------------------------------- -/* */ string pkgTagSection::FindS(const char *Tag) const { const char *Start; @@ -520,6 +518,24 @@ string pkgTagSection::FindS(const char *Tag) const return string(Start,End); } /*}}}*/ +// TagSection::FindRawS - Find a string /*{{{*/ +string pkgTagSection::FindRawS(const char *Tag) const +{ + unsigned int Pos; + if (Find(Tag, Pos) == false) + return ""; + + char const *Start = (char const *) memchr(Section + d->Tags[Pos].EndTag, ':', d->Tags[Pos].StartValue - d->Tags[Pos].EndTag); + ++Start; + char const *End = Section + d->Tags[Pos + 1].StartTag; + if (unlikely(Start > End)) + return ""; + + for (; isspace(End[-1]) != 0 && End > Start; --End); + + return std::string(Start, End - Start); +} + /*}}}*/ // TagSection::FindI - Find an integer /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -623,6 +639,132 @@ APT_PURE unsigned int pkgTagSection::Count() const { /*{{{*/ return d->Tags.size() - 1; } /*}}}*/ +// TagSection::Write - Ordered (re)writing of fields /*{{{*/ +pkgTagSection::Tag pkgTagSection::Tag::Remove(std::string const &Name) +{ + return Tag(REMOVE, Name, ""); +} +pkgTagSection::Tag pkgTagSection::Tag::Rename(std::string const &OldName, std::string const &NewName) +{ + return Tag(RENAME, OldName, NewName); +} +pkgTagSection::Tag pkgTagSection::Tag::Rewrite(std::string const &Name, std::string const &Data) +{ + if (Data.empty() == true) + return Tag(REMOVE, Name, ""); + else + return Tag(REWRITE, Name, Data); +} +static bool WriteTag(FileFd &File, std::string Tag, std::string const &Value) +{ + if (Value.empty() || isspace(Value[0]) != 0) + Tag.append(":"); + else + Tag.append(": "); + Tag.append(Value); + Tag.append("\n"); + return File.Write(Tag.c_str(), Tag.length()); +} +static bool RewriteTags(FileFd &File, pkgTagSection const * const This, char const * const Tag, + std::vector::const_iterator &R, + std::vector::const_iterator const &REnd) +{ + size_t const TagLen = strlen(Tag); + for (; R != REnd; ++R) + { + std::string data; + if (R->Name.length() == TagLen && strncasecmp(R->Name.c_str(), Tag, R->Name.length()) == 0) + { + if (R->Action != pkgTagSection::Tag::REWRITE) + break; + data = R->Data; + } + else if(R->Action == pkgTagSection::Tag::RENAME && R->Data.length() == TagLen && + strncasecmp(R->Data.c_str(), Tag, R->Data.length()) == 0) + data = This->FindRawS(R->Name.c_str()); + else + continue; + + return WriteTag(File, Tag, data); + } + return true; +} +bool pkgTagSection::Write(FileFd &File, char const * const * const Order, std::vector const &Rewrite) const +{ + // first pass: Write everything we have an order for + if (Order != NULL) + { + for (unsigned int I = 0; Order[I] != 0; ++I) + { + std::vector::const_iterator R = Rewrite.begin(); + if (RewriteTags(File, this, Order[I], R, Rewrite.end()) == false) + return false; + if (R != Rewrite.end()) + continue; + + if (Exists(Order[I]) == false) + continue; + + if (WriteTag(File, Order[I], FindRawS(Order[I])) == false) + return false; + } + } + // second pass: See if we have tags which aren't ordered + if (d->Tags.empty() == false) + { + for (std::vector::const_iterator T = d->Tags.begin(); T != d->Tags.end() - 1; ++T) + { + char const * const fieldname = Section + T->StartTag; + size_t fieldnamelen = T->EndTag - T->StartTag; + if (Order != NULL) + { + unsigned int I = 0; + for (; Order[I] != 0; ++I) + { + if (fieldnamelen == strlen(Order[I]) && strncasecmp(fieldname, Order[I], fieldnamelen) == 0) + break; + } + if (Order[I] != 0) + continue; + } + + std::string const name(fieldname, fieldnamelen); + std::vector::const_iterator R = Rewrite.begin(); + if (RewriteTags(File, this, name.c_str(), R, Rewrite.end()) == false) + return false; + if (R != Rewrite.end()) + continue; + + if (WriteTag(File, name, FindRawS(name.c_str())) == false) + return false; + } + } + // last pass: see if there are any rewrites remaining we haven't done yet + for (std::vector::const_iterator R = Rewrite.begin(); R != Rewrite.end(); ++R) + { + if (R->Action == Tag::REMOVE) + continue; + std::string const name = ((R->Action == Tag::RENAME) ? R->Data : R->Name); + if (Exists(name.c_str())) + continue; + if (Order != NULL) + { + unsigned int I = 0; + for (; Order[I] != 0; ++I) + { + if (strncasecmp(name.c_str(), Order[I], name.length()) == 0 && name.length() == strlen(Order[I])) + break; + } + if (Order[I] != 0) + continue; + } + + if (WriteTag(File, name, ((R->Action == Tag::RENAME) ? FindRawS(R->Name.c_str()) : R->Data)) == false) + return false; + } + return true; +} + /*}}}*/ #include "tagfile-order.c" @@ -631,6 +773,7 @@ APT_PURE unsigned int pkgTagSection::Count() const { /*{{{*/ /* This writes the control record to stdout rewriting it as necessary. The override map item specificies the rewriting rules to follow. This also takes the time to sort the feild list. */ +APT_IGNORE_DEPRECATED_PUSH bool TFRewrite(FILE *Output,pkgTagSection const &Tags,const char *Order[], TFRewriteData *Rewrite) { @@ -754,6 +897,7 @@ bool TFRewrite(FILE *Output,pkgTagSection const &Tags,const char *Order[], return true; } +APT_IGNORE_DEPRECATED_POP /*}}}*/ pkgTagSection::~pkgTagSection() { delete d; } diff --git a/apt-pkg/tagfile.h b/apt-pkg/tagfile.h index d09e7046c..118954541 100644 --- a/apt-pkg/tagfile.h +++ b/apt-pkg/tagfile.h @@ -54,13 +54,14 @@ class pkgTagSection const char *Stop; public: - + inline bool operator ==(const pkgTagSection &rhs) {return Section == rhs.Section;}; inline bool operator !=(const pkgTagSection &rhs) {return Section != rhs.Section;}; - + bool Find(const char *Tag,const char *&Start, const char *&End) const; bool Find(const char *Tag,unsigned int &Pos) const; std::string FindS(const char *Tag) const; + std::string FindRawS(const char *Tag) const; 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; @@ -115,9 +116,32 @@ class pkgTagSection Start = Section; Stop = this->Stop; }; - + pkgTagSection(); virtual ~pkgTagSection(); + + struct Tag + { + enum ActionType { REMOVE, RENAME, REWRITE } Action; + std::string Name; + std::string Data; + + static Tag Remove(std::string const &Name); + static Tag Rename(std::string const &OldName, std::string const &NewName); + static Tag Rewrite(std::string const &Name, std::string const &Data); + private: + Tag(ActionType const Action, std::string const &Name, std::string const &Data) : + Action(Action), Name(Name), Data(Data) {} + }; + + /** Write this section (with optional rewrites) to a file + * + * @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 + * @return \b true if successful, otherwise \b false + */ + bool Write(FileFd &File, char const * const * const Order = NULL, std::vector const &Rewrite = std::vector()) const; }; class pkgTagFilePrivate; @@ -141,20 +165,19 @@ class pkgTagFile virtual ~pkgTagFile(); }; -/* This is the list of things to rewrite. The rewriter - goes through and changes or adds each of these headers - to suit. A zero forces the header to be erased, an empty string - causes the old value to be used. (rewrite rule ignored) */ -struct TFRewriteData +extern const char **TFRewritePackageOrder; +extern const char **TFRewriteSourceOrder; + +// Use pkgTagSection::Tag and pkgTagSection::Write() instead +APT_IGNORE_DEPRECATED_PUSH +struct APT_DEPRECATED TFRewriteData { const char *Tag; const char *Rewrite; const char *NewTag; }; -extern const char **TFRewritePackageOrder; -extern const char **TFRewriteSourceOrder; - -bool TFRewrite(FILE *Output,pkgTagSection const &Tags,const char *Order[], +APT_DEPRECATED bool TFRewrite(FILE *Output,pkgTagSection const &Tags,const char *Order[], TFRewriteData *Rewrite); +APT_IGNORE_DEPRECATED_POP #endif -- cgit v1.2.3 From 88593886a42025d51d76051da5929b044e42efee Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 11 May 2015 15:08:08 +0200 Subject: rewrite all TFRewrite instances to use the new pkgTagSection::Write MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While it is mostly busywork to rewrite all instances it actually fixes bugs as the data storage used by the new method is std::string rather than a char*, the later mostly created by c_str() from a std::string which the caller has to ensure keeps in scope – something apt-ftparchive actually didn't ensure and relied on copy-on-write behavior instead which c++11 forbids and hence the new default gcc abi doesn't use it. --- apt-pkg/depcache.cc | 50 +++++++++------------ apt-pkg/indexcopy.cc | 125 ++++++++++++++++++++------------------------------- apt-pkg/indexcopy.h | 7 +-- 3 files changed, 73 insertions(+), 109 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 73c5bb320..b73c336db 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -33,7 +33,6 @@ #include #include #include -#include #include #include @@ -252,17 +251,14 @@ bool pkgDepCache::writeStateFile(OpProgress * /*prog*/, bool InstalledOnly) /*{{ return _error->Error(_("Failed to open StateFile %s"), state.c_str()); - FILE *OutFile; - string const outfile = state + ".tmp"; - if((OutFile = fopen(outfile.c_str(),"w")) == NULL) - return _error->Error(_("Failed to write temporary StateFile %s"), - outfile.c_str()); + FileFd OutFile(state, FileFd::ReadWrite | FileFd::Atomic); + if (OutFile.IsOpen() == false || OutFile.Failed() == true) + return _error->Error(_("Failed to write temporary StateFile %s"), state.c_str()); // first merge with the existing sections pkgTagFile tagfile(&StateFile); pkgTagSection section; std::set pkgs_seen; - const char *nullreorderlist[] = {0}; while(tagfile.Step(section)) { string const pkgname = section.FindS("Package"); string pkgarch = section.FindS("Architecture"); @@ -271,7 +267,7 @@ bool pkgDepCache::writeStateFile(OpProgress * /*prog*/, bool InstalledOnly) /*{{ // Silently ignore unknown packages and packages with no actual // version. pkgCache::PkgIterator pkg = Cache->FindPkg(pkgname, pkgarch); - if(pkg.end() || pkg.VersionList().end()) + if(pkg.end() || pkg.VersionList().end()) continue; StateCache const &P = PkgState[pkg->ID]; bool newAuto = (P.Flags & Flag::Auto); @@ -292,21 +288,17 @@ bool pkgDepCache::writeStateFile(OpProgress * /*prog*/, bool InstalledOnly) /*{{ if(_config->FindB("Debug::pkgAutoRemove",false)) std::clog << "Update existing AutoInstall info: " << pkg.FullName() << std::endl; - TFRewriteData rewrite[3]; - rewrite[0].Tag = "Architecture"; - rewrite[0].Rewrite = pkg.Arch(); - rewrite[0].NewTag = 0; - rewrite[1].Tag = "Auto-Installed"; - rewrite[1].Rewrite = newAuto ? "1" : "0"; - rewrite[1].NewTag = 0; - rewrite[2].Tag = 0; - TFRewrite(OutFile, section, nullreorderlist, rewrite); - fprintf(OutFile,"\n"); + + std::vector rewrite; + rewrite.push_back(pkgTagSection::Tag::Rewrite("Architecture", pkg.Arch())); + rewrite.push_back(pkgTagSection::Tag::Rewrite("Auto-Installed", newAuto ? "1" : "0")); + section.Write(OutFile, NULL, rewrite); + if (OutFile.Write("\n", 1) == false) + return false; pkgs_seen.insert(pkg.FullName()); } - + // then write the ones we have not seen yet - std::ostringstream ostr; for(pkgCache::PkgIterator pkg=Cache->PkgBegin(); !pkg.end(); ++pkg) { StateCache const &P = PkgState[pkg->ID]; if(P.Flags & Flag::Auto) { @@ -325,19 +317,17 @@ bool pkgDepCache::writeStateFile(OpProgress * /*prog*/, bool InstalledOnly) /*{{ continue; if(debug_autoremove) std::clog << "Writing new AutoInstall: " << pkg.FullName() << std::endl; - ostr.str(string("")); - ostr << "Package: " << pkg.Name() - << "\nArchitecture: " << pkgarch - << "\nAuto-Installed: 1\n\n"; - fprintf(OutFile,"%s",ostr.str().c_str()); + std::string stanza = "Package: "; + stanza.append(pkg.Name()) + .append("\nArchitecture: ").append(pkgarch) + .append("\nAuto-Installed: 1\n\n"); + if (OutFile.Write(stanza.c_str(), stanza.length()) == false) + return false; } } - fclose(OutFile); - - // move the outfile over the real file and set permissions - rename(outfile.c_str(), state.c_str()); + if (OutFile.Close() == false) + return false; chmod(state.c_str(), 0644); - return true; } /*}}}*/ diff --git a/apt-pkg/indexcopy.cc b/apt-pkg/indexcopy.cc index 144c508be..461aa4217 100644 --- a/apt-pkg/indexcopy.cc +++ b/apt-pkg/indexcopy.cc @@ -108,10 +108,7 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector &List, } if (_error->PendingError() == true) return false; - FILE *TargetFl = fdopen(dup(Target.Fd()),"w"); - if (TargetFl == 0) - return _error->Errno("fdopen","Failed to reopen fd"); - + // Setup the progress meter if(Progress) Progress->OverallProgress(CurrentSize,TotalSize,FileSize, @@ -132,14 +129,11 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector &List, string File; unsigned long long Size; if (GetFile(File,Size) == false) - { - fclose(TargetFl); return false; - } - + if (Chop != 0) File = OrigPath + ChopDirs(File,Chop); - + // See if the file exists if (NoStat == false || Hits < 10) { @@ -157,10 +151,10 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector &List, if (Chop != 0) File = OrigPath + ChopDirs(File,Chop); } - + // Get the size struct stat Buf; - if (stat((CDROM + Prefix + File).c_str(),&Buf) != 0 || + if (stat((CDROM + Prefix + File).c_str(),&Buf) != 0 || Buf.st_size == 0) { bool Mangled = false; @@ -173,7 +167,7 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector &List, File.replace(Start,End-Start,"binary-all"); Mangled = true; } - + if (Mangled == false || stat((CDROM + Prefix + File).c_str(),&Buf) != 0) { @@ -181,9 +175,9 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector &List, clog << "Missed(2): " << OrigFile << endl; NotFound++; continue; - } - } - + } + } + // Size match if ((unsigned long long)Buf.st_size != Size) { @@ -193,21 +187,17 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector &List, continue; } } - + Packages++; Hits++; - - if (RewriteEntry(TargetFl,File) == false) - { - fclose(TargetFl); + + if (RewriteEntry(Target, File) == false) return false; - } } - fclose(TargetFl); if (Debug == true) cout << " Processed by using Prefix '" << Prefix << "' and chop " << Chop << endl; - + if (_config->FindB("APT::CDROM::NoAct",false) == false) { // Move out of the partial directory @@ -218,39 +208,38 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector &List, return _error->Errno("rename","Failed to rename"); ChangeOwnerAndPermissionOfFile("CopyPackages", FinalF.c_str(), "root", "root", 0644); } - + /* Mangle the source to be in the proper notation with - prefix dist [component] */ + prefix dist [component] */ *I = string(*I,Prefix.length()); ConvertToSourceList(CDROM,*I); *I = Prefix + ' ' + *I; - + CurrentSize += FileSize; - } + } if(Progress) Progress->Done(); - + // Some stats if(log) { stringstream msg; if(NotFound == 0 && WrongSize == 0) ioprintf(msg, _("Wrote %i records.\n"), Packages); else if (NotFound != 0 && WrongSize == 0) - ioprintf(msg, _("Wrote %i records with %i missing files.\n"), + ioprintf(msg, _("Wrote %i records with %i missing files.\n"), Packages, NotFound); else if (NotFound == 0 && WrongSize != 0) - ioprintf(msg, _("Wrote %i records with %i mismatched files\n"), + ioprintf(msg, _("Wrote %i records with %i mismatched files\n"), Packages, WrongSize); if (NotFound != 0 && WrongSize != 0) ioprintf(msg, _("Wrote %i records with %i missing files and %i mismatched files\n"), Packages, NotFound, WrongSize); } - + if (Packages == 0) _error->Warning("No valid records were found."); if (NotFound + WrongSize > 10) _error->Warning("A lot of entries were discarded, something may be wrong.\n"); - return true; } @@ -267,10 +256,10 @@ string IndexCopy::ChopDirs(string Path,unsigned int Depth) Depth--; } while (I != string::npos && Depth != 0); - + if (I == string::npos) return string(); - + return string(Path,I+1); } /*}}}*/ @@ -433,17 +422,15 @@ bool PackageCopy::GetFile(string &File,unsigned long long &Size) } /*}}}*/ // PackageCopy::RewriteEntry - Rewrite the entry with a new filename /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool PackageCopy::RewriteEntry(FILE *Target,string File) +bool PackageCopy::RewriteEntry(FileFd &Target,string const &File) { - TFRewriteData Changes[] = {{ "Filename", File.c_str(), NULL }, - { NULL, NULL, NULL }}; - - if (TFRewrite(Target,*Section,TFRewritePackageOrder,Changes) == false) + string const Dir(File,0,File.rfind('/')); + std::vector Changes; + Changes.push_back(pkgTagSection::Tag::Rewrite("Filename", File)); + + if (Section->Write(Target, TFRewritePackageOrder, Changes) == false) return false; - fputc('\n',Target); - return true; + return Target.Write("\n", 1); } /*}}}*/ // SourceCopy::GetFile - Get the file information from the section /*{{{*/ @@ -478,23 +465,18 @@ bool SourceCopy::GetFile(string &File,unsigned long long &Size) } /*}}}*/ // SourceCopy::RewriteEntry - Rewrite the entry with a new filename /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool SourceCopy::RewriteEntry(FILE *Target,string File) +bool SourceCopy::RewriteEntry(FileFd &Target, std::string const &File) { - string Dir(File,0,File.rfind('/')); - TFRewriteData Changes[] = {{ "Directory", Dir.c_str(), NULL }, - { NULL, NULL, NULL }}; - - if (TFRewrite(Target,*Section,TFRewriteSourceOrder,Changes) == false) + string const Dir(File,0,File.rfind('/')); + std::vector Changes; + Changes.push_back(pkgTagSection::Tag::Rewrite("Directory", Dir)); + + if (Section->Write(Target, TFRewriteSourceOrder, Changes) == false) return false; - fputc('\n',Target); - return true; + return Target.Write("\n", 1); } /*}}}*/ -// SigVerify::Verify - Verify a files md5sum against its metaindex /*{{{*/ -// --------------------------------------------------------------------- -/* */ +// SigVerify::Verify - Verify a files md5sum against its metaindex /*{{{*/ bool SigVerify::Verify(string prefix, string file, indexRecords *MetaIndex) { const indexRecords::checkSum *Record = MetaIndex->Lookup(file); @@ -702,7 +684,7 @@ bool TranslationsCopy::CopyTranslations(string CDROM,string Name, /*{{{*/ pkgTagFile Parser(&Pkg); if (_error->PendingError() == true) return false; - + // Open the output file char S[400]; snprintf(S,sizeof(S),"cdrom:[%s]/%s",Name.c_str(), @@ -719,10 +701,7 @@ bool TranslationsCopy::CopyTranslations(string CDROM,string Name, /*{{{*/ } if (_error->PendingError() == true) return false; - FILE *TargetFl = fdopen(dup(Target.Fd()),"w"); - if (TargetFl == 0) - return _error->Errno("fdopen","Failed to reopen fd"); - + // Setup the progress meter if(Progress) Progress->OverallProgress(CurrentSize,TotalSize,FileSize, @@ -740,20 +719,16 @@ bool TranslationsCopy::CopyTranslations(string CDROM,string Name, /*{{{*/ if(Progress) Progress->Progress(Parser.Offset()); - const char *Start; - const char *Stop; - Section.GetSection(Start,Stop); - fwrite(Start,Stop-Start, 1, TargetFl); - fputc('\n',TargetFl); + if (Section.Write(Target) == false || Target.Write("\n", 1) == false) + return false; Packages++; Hits++; } - fclose(TargetFl); if (Debug == true) cout << " Processed by using Prefix '" << Prefix << "' and chop " << endl; - + if (_config->FindB("APT::CDROM::NoAct",false) == false) { // Move out of the partial directory @@ -764,34 +739,32 @@ bool TranslationsCopy::CopyTranslations(string CDROM,string Name, /*{{{*/ return _error->Errno("rename","Failed to rename"); ChangeOwnerAndPermissionOfFile("CopyTranslations", FinalF.c_str(), "root", "root", 0644); } - - + CurrentSize += FileSize; - } + } if(Progress) Progress->Done(); - + // Some stats if(log) { stringstream msg; if(NotFound == 0 && WrongSize == 0) ioprintf(msg, _("Wrote %i records.\n"), Packages); else if (NotFound != 0 && WrongSize == 0) - ioprintf(msg, _("Wrote %i records with %i missing files.\n"), + ioprintf(msg, _("Wrote %i records with %i missing files.\n"), Packages, NotFound); else if (NotFound == 0 && WrongSize != 0) - ioprintf(msg, _("Wrote %i records with %i mismatched files\n"), + ioprintf(msg, _("Wrote %i records with %i mismatched files\n"), Packages, WrongSize); if (NotFound != 0 && WrongSize != 0) ioprintf(msg, _("Wrote %i records with %i missing files and %i mismatched files\n"), Packages, NotFound, WrongSize); } - + if (Packages == 0) _error->Warning("No valid records were found."); if (NotFound + WrongSize > 10) _error->Warning("A lot of entries were discarded, something may be wrong.\n"); - return true; } diff --git a/apt-pkg/indexcopy.h b/apt-pkg/indexcopy.h index 701beb075..729b0c8cb 100644 --- a/apt-pkg/indexcopy.h +++ b/apt-pkg/indexcopy.h @@ -28,6 +28,7 @@ using std::vector; class pkgTagSection; class indexRecords; class pkgCdromStatus; +class FileFd; class IndexCopy /*{{{*/ { @@ -45,7 +46,7 @@ class IndexCopy /*{{{*/ void ConvertToSourceList(std::string CD,std::string &Path); bool GrabFirst(std::string Path,std::string &To,unsigned int Depth); virtual bool GetFile(std::string &Filename,unsigned long long &Size) = 0; - virtual bool RewriteEntry(FILE *Target,std::string File) = 0; + virtual bool RewriteEntry(FileFd &Target, std::string const &File) = 0; virtual const char *GetFileName() = 0; virtual const char *Type() = 0; @@ -61,7 +62,7 @@ class PackageCopy : public IndexCopy /*{{{*/ protected: virtual bool GetFile(std::string &Filename,unsigned long long &Size); - virtual bool RewriteEntry(FILE *Target,std::string File); + virtual bool RewriteEntry(FileFd &Target, std::string const &File); virtual const char *GetFileName() {return "Packages";}; virtual const char *Type() {return "Package";}; @@ -72,7 +73,7 @@ class SourceCopy : public IndexCopy /*{{{*/ protected: virtual bool GetFile(std::string &Filename,unsigned long long &Size); - virtual bool RewriteEntry(FILE *Target,std::string File); + virtual bool RewriteEntry(FileFd &Target, std::string const &File); virtual const char *GetFileName() {return "Sources";}; virtual const char *Type() {return "Source";}; -- cgit v1.2.3 From 495b7a615a2d8f485beadf88c6ed298f5bbe50c2 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 12 May 2015 11:18:17 +0200 Subject: implement VerifyFile as all-hashes check It isn't used much compared to what the methodname suggests, but in the remaining uses it can't hurt to check more than strictly necessary by calculating and verifying with all hashes we can compare with rather than "just" the best known hash. --- apt-pkg/acquire-item.cc | 2 +- apt-pkg/contrib/hashes.cc | 21 ++++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 01ce0e650..1090912f5 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -1175,7 +1175,7 @@ void pkgAcqIndexMergeDiffs::Done(string Message,unsigned long long Size,HashStri else if (State == StateApplyDiff) { // see if we really got the expected file - if(ExpectedHashes.usable() && !ExpectedHashes.VerifyFile(DestFile)) + if(ExpectedHashes.usable() && ExpectedHashes != Hashes) { RenameOnError(HashSumMismatch); return; diff --git a/apt-pkg/contrib/hashes.cc b/apt-pkg/contrib/hashes.cc index 953465091..0fa443b4a 100644 --- a/apt-pkg/contrib/hashes.cc +++ b/apt-pkg/contrib/hashes.cc @@ -204,15 +204,22 @@ bool HashStringList::push_back(const HashString &hashString) /*{{{*/ /*}}}*/ bool HashStringList::VerifyFile(std::string filename) const /*{{{*/ { - if (list.empty() == true) - return false; - HashString const * const hs = find(NULL); - if (hs == NULL || hs->VerifyFile(filename) == false) + if (usable() == false) return false; + + Hashes hashes(*this); + FileFd file(filename, FileFd::ReadOnly); HashString const * const hsf = find("Checksum-FileSize"); - if (hsf != NULL && hsf->VerifyFile(filename) == false) - return false; - return true; + if (hsf != NULL) + { + std::string fileSize; + strprintf(fileSize, "%llu", file.FileSize()); + if (hsf->HashValue() != fileSize) + return false; + } + hashes.AddFD(file); + HashStringList const hsl = hashes.GetHashStringList(); + return hsl == *this; } /*}}}*/ bool HashStringList::operator==(HashStringList const &other) const /*{{{*/ -- cgit v1.2.3 From 8eafc759544298211cd0bfaa3919afc0fadd47d1 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 13 May 2015 16:09:12 +0200 Subject: detect Releasefile IMS hits even if the server doesn't Not all servers we are talking to support If-Modified-Since and some are not even sending Last-Modified for us, so in an effort to detect such hits we run a hashsum check on the 'old' compared to the 'new' file, we got the hashes for the 'new' already for "free" from the methods anyway and hence just need to calculated the old ones. This allows us to detect hits even with unsupported servers, which in turn means we benefit from all the new hit behavior also here. --- apt-pkg/acquire-item.cc | 31 +++++++++++++++++++++++-------- apt-pkg/acquire-item.h | 2 +- apt-pkg/acquire-worker.cc | 8 ++++---- 3 files changed, 28 insertions(+), 13 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 1090912f5..78dace12c 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -253,7 +253,10 @@ bool pkgAcquire::Item::Rename(string From,string To) strprintf(S, _("rename failed, %s (%s -> %s)."), strerror(errno), From.c_str(),To.c_str()); Status = StatError; - ErrorText += S; + if (ErrorText.empty()) + ErrorText = S; + else + ErrorText = ErrorText + ": " + S; return false; } /*}}}*/ @@ -1794,7 +1797,7 @@ void pkgAcqMetaSig::Done(string Message,unsigned long long Size, if(AuthPass == false) { - if(CheckDownloadDone(Message) == true) + if(CheckDownloadDone(Message, Hashes) == true) { // destfile will be modified to point to MetaIndexFile for the // gpgv method, so we need to save it here @@ -1837,7 +1840,8 @@ void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)/*{{{*/ Status = StatDone; } else { _error->Error("%s", downgrade_msg.c_str()); - Rename(MetaIndexFile, MetaIndexFile+".FAILED"); + if (TransactionManager->IMSHit == false) + Rename(MetaIndexFile, MetaIndexFile+".FAILED"); Item::Failed("Message: " + downgrade_msg, Cnf); TransactionManager->AbortTransaction(); return; @@ -1922,12 +1926,12 @@ void pkgAcqMetaIndex::Done(string Message,unsigned long long Size, /*{{{*/ { Item::Done(Message,Size,Hashes,Cfg); - if(CheckDownloadDone(Message)) + if(CheckDownloadDone(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 - std::string MetaIndexFile = DestFile; + std::string const MetaIndexFile = DestFile; new pkgAcqMetaSig(Owner, TransactionManager, MetaIndexSigURI, MetaIndexSigURIDesc, MetaIndexSigShortDesc, MetaIndexFile, IndexTargets, @@ -2008,7 +2012,7 @@ void pkgAcqMetaBase::QueueForSignatureVerify(const std::string &MetaIndexFile, } /*}}}*/ // pkgAcqMetaBase::CheckDownloadDone /*{{{*/ -bool pkgAcqMetaBase::CheckDownloadDone(const std::string &Message) +bool pkgAcqMetaBase::CheckDownloadDone(const std::string &Message, HashStringList const &Hashes) { // We have just finished downloading a Release file (it is not // verified yet) @@ -2031,7 +2035,18 @@ 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) + if (IMSHit == false) + { + // detect IMS-Hits servers haven't detected by Hash comparison + std::string FinalFile = GetFinalFilename(); + if (RealFileExists(FinalFile) && Hashes.VerifyFile(FinalFile) == true) + { + IMSHit = true; + unlink(DestFile.c_str()); + } + } + + if(IMSHit == true) { // for simplicity, the transaction manager is always InRelease // even if it doesn't exist. @@ -2273,7 +2288,7 @@ void pkgAcqMetaClearSig::Done(std::string Message,unsigned long long Size, if(AuthPass == false) { - if(CheckDownloadDone(Message) == true) + if(CheckDownloadDone(Message, Hashes) == true) QueueForSignatureVerify(DestFile, DestFile); return; } diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index 33a28671c..646de8416 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -429,7 +429,7 @@ class pkgAcqMetaBase : public pkgAcquire::Item /*{{{*/ * \param Message The message block received from the fetch * subprocess. */ - bool CheckDownloadDone(const std::string &Message); + bool CheckDownloadDone(const std::string &Message, HashStringList const &Hashes); /** \brief Queue the downloaded Signature for verification */ void QueueForSignatureVerify(const std::string &MetaIndexFile, diff --git a/apt-pkg/acquire-worker.cc b/apt-pkg/acquire-worker.cc index bee01e620..9254e20a3 100644 --- a/apt-pkg/acquire-worker.cc +++ b/apt-pkg/acquire-worker.cc @@ -333,13 +333,12 @@ bool pkgAcquire::Worker::RunMessages() // see if there is a hash to verify HashStringList ReceivedHashes; - HashStringList expectedHashes = Owner->HashSums(); - for (HashStringList::const_iterator hs = expectedHashes.begin(); hs != expectedHashes.end(); ++hs) + for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type) { - std::string const tagname = hs->HashType() + "-Hash"; + 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(hs->HashType(), hashsum)); + ReceivedHashes.push_back(HashString(*type, hashsum)); } if(_config->FindB("Debug::pkgAcquire::Auth", false) == true) @@ -349,6 +348,7 @@ bool pkgAcquire::Worker::RunMessages() 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; -- cgit v1.2.3 From 6bf93605fdb8e858d3f0a79a124c1d39f760094d Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 18 May 2015 22:15:06 +0200 Subject: treat older Release files than we already have as an IMSHit Valid-Until protects us from long-living downgrade attacks, but not all repositories have it and an attacker could still use older but still valid files to downgrade us. While this makes it sounds like a security improvement now, its a bit theoretical at best as an attacker with capabilities to pull this off could just as well always keep us days (but in the valid period) behind and always knows which state we have, as we tell him with the If-Modified-Since header. This is also why this is 'silently' ignored and treated as an IMSHit rather than screamed at the user as this can at best be an annoyance for attackers. An error here would 'regularily' be encountered by users by out-of-sync mirrors serving a single run (e.g. load balancer) or in two consecutive runs on the other hand, so it would just help teaching people ignore it. That said, most of the code churn is caused by enforcing this additional requirement. Crisscross from InRelease to Release.gpg is e.g. very unlikely in practice, but if we would ignore it an attacker could sidestep it this way. --- apt-pkg/acquire-item.cc | 264 ++++++++++++++++++++++++++++++++++-------------- apt-pkg/acquire-item.h | 105 ++++++++++--------- apt-pkg/indexrecords.cc | 28 ++--- apt-pkg/indexrecords.h | 2 + 4 files changed, 262 insertions(+), 137 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 78dace12c..8155b9bfe 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -1637,7 +1637,7 @@ pkgAcqMetaBase::pkgAcqMetaBase(pkgAcquire *Owner, HashStringList const &ExpectedHashes, pkgAcqMetaBase *TransactionManager) : Item(Owner, ExpectedHashes, TransactionManager), - MetaIndexParser(MetaIndexParser), IndexTargets(IndexTargets), + MetaIndexParser(MetaIndexParser), LastMetaIndexParser(NULL), IndexTargets(IndexTargets), AuthPass(false), RealURI(RealURI), IMSHit(false) { } @@ -1697,6 +1697,14 @@ void pkgAcqMetaBase::CommitTransaction() 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, @@ -1715,15 +1723,15 @@ void pkgAcqMetaBase::TransactionStageRemoval(Item *I, } /*}}}*/ // AcqMetaBase::GenerateAuthWarning - Check gpg authentication error /*{{{*/ -bool pkgAcqMetaBase::CheckStopAuthentication(const std::string &Message) +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 = GetFinalFilename(); + string const Final = I->GetFinalFilename(); if(FileExists(Final)) { - Status = StatTransientNetworkError; + 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. " @@ -1737,7 +1745,7 @@ bool pkgAcqMetaBase::CheckStopAuthentication(const std::string &Message) _error->Error(_("GPG error: %s: %s"), Desc.Description.c_str(), LookupTag(Message,"Message").c_str()); - Status = StatError; + I->Status = StatError; return true; } else { _error->Warning(_("GPG error: %s: %s"), @@ -1751,17 +1759,13 @@ bool pkgAcqMetaBase::CheckStopAuthentication(const std::string &Message) /*}}}*/ // AcqMetaSig::AcqMetaSig - Constructor /*{{{*/ pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner, - pkgAcqMetaBase *TransactionManager, - string URI,string URIDesc,string ShortDesc, - string MetaIndexFile, - const vector* IndexTargets, - indexRecords* MetaIndexParser) : - pkgAcqMetaBase(Owner, IndexTargets, MetaIndexParser, URI, - HashStringList(), TransactionManager), - MetaIndexFile(MetaIndexFile), URIDesc(URIDesc), - ShortDesc(ShortDesc) + 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(RealURI); + DestFile = GetPartialFileNameFromURI(URI); // remove any partial downloaded sig-file in partial/. // it may confuse proxies and is too small to warrant a @@ -1779,11 +1783,28 @@ pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner, Desc.ShortDesc = ShortDesc; Desc.URI = URI; - QueueURI(Desc); + // 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 /*{{{*/ @@ -1793,21 +1814,32 @@ 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(AuthPass == false) + if(MetaIndex->AuthPass == false) { - if(CheckDownloadDone(Message, Hashes) == true) + 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; - QueueForSignatureVerify(MetaIndexFile, MetaIndexFileSignature); + // 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(CheckAuthDone(Message) == true) - TransactionManager->TransactionStageCopy(this, MetaIndexFileSignature, GetFinalFilename()); + 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)/*{{{*/ @@ -1815,20 +1847,18 @@ void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)/*{{{*/ Item::Failed(Message,Cnf); // check if we need to fail at this point - if (AuthPass == true && CheckStopAuthentication(Message)) + if (MetaIndex->AuthPass == true && MetaIndex->CheckStopAuthentication(this, Message)) return; - // FIXME: meh, this is not really elegant - string const Final = GetFinalFileNameFromURI(RealURI); - string const InReleaseURI = RealURI.replace(RealURI.rfind("Release.gpg"), 12, - "InRelease"); - string const FinalInRelease = GetFinalFileNameFromURI(InReleaseURI); + string const FinalRelease = MetaIndex->GetFinalFilename(); + string const FinalReleasegpg = GetFinalFilename(); + string const FinalInRelease = TransactionManager->GetFinalFilename(); - if (RealFileExists(Final) || RealFileExists(FinalInRelease)) + if (RealFileExists(FinalReleasegpg) || RealFileExists(FinalInRelease)) { std::string downgrade_msg; strprintf(downgrade_msg, _("The repository '%s' is no longer signed."), - URIDesc.c_str()); + MetaIndex->URIDesc.c_str()); if(_config->FindB("Acquire::AllowDowngradeToInsecureRepositories")) { // meh, the users wants to take risks (we still mark the packages @@ -1841,7 +1871,7 @@ void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)/*{{{*/ } else { _error->Error("%s", downgrade_msg.c_str()); if (TransactionManager->IMSHit == false) - Rename(MetaIndexFile, MetaIndexFile+".FAILED"); + Rename(MetaIndex->DestFile, MetaIndex->DestFile + ".FAILED"); Item::Failed("Message: " + downgrade_msg, Cnf); TransactionManager->AbortTransaction(); return; @@ -1850,23 +1880,44 @@ void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)/*{{{*/ else _error->Warning(_("The data from '%s' is not signed. Packages " "from that repository can not be authenticated."), - URIDesc.c_str()); + MetaIndex->URIDesc.c_str()); - // this ensures that any file in the lists/ dir is removed by the - // transaction - DestFile = GetPartialFileNameFromURI(RealURI); + // 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(MetaIndexParser, TransactionManager, this) == true) + 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 - MetaIndexParser->Load(MetaIndexFile); - if (!VerifyVendor(Message)) + MetaIndex->MetaIndexParser->Load(MetaIndex->DestFile); + if (MetaIndex->VerifyVendor(Message) == false) /* expired Release files are still a problem you need extra force for */; else - QueueIndexes(true); + MetaIndex->QueueIndexes(true); + + TransactionManager->TransactionStageCopy(MetaIndex, MetaIndex->DestFile, MetaIndex->GetFinalFilename()); } // FIXME: this is used often (e.g. in pkgAcqIndexTrans) so refactor @@ -1926,18 +1977,14 @@ void pkgAcqMetaIndex::Done(string Message,unsigned long long Size, /*{{{*/ { Item::Done(Message,Size,Hashes,Cfg); - if(CheckDownloadDone(Message, Hashes)) + 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 - std::string const MetaIndexFile = DestFile; - new pkgAcqMetaSig(Owner, TransactionManager, + new pkgAcqMetaSig(Owner, TransactionManager, MetaIndexSigURI, MetaIndexSigURIDesc, - MetaIndexSigShortDesc, MetaIndexFile, IndexTargets, - MetaIndexParser); - - TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename()); + MetaIndexSigShortDesc, this); } } /*}}}*/ @@ -1948,6 +1995,40 @@ bool pkgAcqMetaBase::CheckAuthDone(string Message) /*{{{*/ // 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; @@ -2001,48 +2082,47 @@ std::string pkgAcqMetaBase::GetFinalFilename() const } /*}}}*/ // pkgAcqMetaBase::QueueForSignatureVerify /*{{{*/ -void pkgAcqMetaBase::QueueForSignatureVerify(const std::string &MetaIndexFile, - const std::string &MetaIndexFileSignature) +void pkgAcqMetaBase::QueueForSignatureVerify(pkgAcquire::Item * const I, std::string const &File, std::string const &Signature) { AuthPass = true; - Desc.URI = "gpgv:" + MetaIndexFileSignature; - DestFile = MetaIndexFile; - QueueURI(Desc); - SetActiveSubprocess("gpgv"); + I->Desc.URI = "gpgv:" + Signature; + I->DestFile = File; + QueueURI(I->Desc); + I->SetActiveSubprocess("gpgv"); } /*}}}*/ // pkgAcqMetaBase::CheckDownloadDone /*{{{*/ -bool pkgAcqMetaBase::CheckDownloadDone(const std::string &Message, HashStringList const &Hashes) +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 FileName = LookupTag(Message,"Filename"); + string const FileName = LookupTag(Message,"Filename"); if (FileName.empty() == true) { - Status = StatError; - ErrorText = "Method gave a blank filename"; + I->Status = StatError; + I->ErrorText = "Method gave a blank filename"; return false; } - if (FileName != DestFile) + if (FileName != I->DestFile) { - Local = true; - Desc.URI = "copy:" + FileName; - QueueURI(Desc); + 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 - IMSHit = StringToBool(LookupTag(Message,"IMS-Hit"),false); - if (IMSHit == false) + 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 FinalFile = GetFinalFilename(); + std::string const FinalFile = I->GetFinalFilename(); if (RealFileExists(FinalFile) && Hashes.VerifyFile(FinalFile) == true) { IMSHit = true; - unlink(DestFile.c_str()); + unlink(I->DestFile.c_str()); } } @@ -2052,11 +2132,11 @@ bool pkgAcqMetaBase::CheckDownloadDone(const std::string &Message, HashStringLis // even if it doesn't exist. if (TransactionManager != NULL) TransactionManager->IMSHit = true; - DestFile = GetFinalFilename(); + I->PartialFile = I->DestFile = I->GetFinalFilename(); } // set Item to complete as the remaining work is all local (verify etc) - Complete = true; + I->Complete = true; return true; } @@ -2175,6 +2255,19 @@ bool pkgAcqMetaBase::VerifyVendor(string Message) /*{{{*/ } } + /* 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; @@ -2248,7 +2341,6 @@ pkgAcqMetaClearSig::pkgAcqMetaClearSig(pkgAcquire *Owner, /*{{{*/ { // index targets + (worst case:) Release/Release.gpg ExpectedAdditionalItems = IndexTargets->size() + 2; - } /*}}}*/ pkgAcqMetaClearSig::~pkgAcqMetaClearSig() /*{{{*/ @@ -2268,14 +2360,25 @@ string pkgAcqMetaClearSig::Custom600Headers() } /*}}}*/ // 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 (InRelase), ensure that + // 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)) @@ -2288,12 +2391,23 @@ void pkgAcqMetaClearSig::Done(std::string Message,unsigned long long Size, if(AuthPass == false) { - if(CheckDownloadDone(Message, Hashes) == true) - QueueForSignatureVerify(DestFile, DestFile); + if(CheckDownloadDone(this, Message, Hashes) == true) + QueueForSignatureVerify(this, DestFile, DestFile); return; } else if(CheckAuthDone(Message) == true) - TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename()); + { + 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) /*{{{*/ @@ -2318,7 +2432,7 @@ void pkgAcqMetaClearSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /* } else { - if(CheckStopAuthentication(Message)) + if(CheckStopAuthentication(this, Message)) return; _error->Warning(_("The data from '%s' is not signed. Packages " diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index 646de8416..07c86f31b 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -394,6 +394,7 @@ class pkgAcqMetaBase : public pkgAcquire::Item /*{{{*/ /** \brief A package-system-specific parser for the meta-index file. */ indexRecords *MetaIndexParser; + indexRecords *LastMetaIndexParser; /** \brief The index files which should be looked up in the meta-index * and then downloaded. @@ -429,11 +430,10 @@ class pkgAcqMetaBase : public pkgAcquire::Item /*{{{*/ * \param Message The message block received from the fetch * subprocess. */ - bool CheckDownloadDone(const std::string &Message, HashStringList const &Hashes); + bool CheckDownloadDone(pkgAcquire::Item * const I, const std::string &Message, HashStringList const &Hashes) const; /** \brief Queue the downloaded Signature for verification */ - void QueueForSignatureVerify(const std::string &MetaIndexFile, - const std::string &MetaIndexFileSignature); + void QueueForSignatureVerify(pkgAcquire::Item * const I, std::string const &File, std::string const &Signature); #if APT_PKG_ABI >= 413 virtual std::string Custom600Headers() const; @@ -453,7 +453,7 @@ class pkgAcqMetaBase : public pkgAcquire::Item /*{{{*/ bool CheckAuthDone(std::string Message); /** Check if the current item should fail at this point */ - bool CheckStopAuthentication(const std::string &Message); + bool CheckStopAuthentication(pkgAcquire::Item * const I, const std::string &Message); /** \brief Check that the release file is a release file for the * correct distribution. @@ -462,8 +462,7 @@ class pkgAcqMetaBase : public pkgAcquire::Item /*{{{*/ */ bool VerifyVendor(std::string Message); - /** \brief Get the full pathname of the final file for the current URI */ - virtual std::string GetFinalFilename() const; + virtual bool TransactionState(TransactionStates const state); public: // This refers more to the Transaction-Manager than the actual file @@ -487,6 +486,9 @@ class pkgAcqMetaBase : public pkgAcquire::Item /*{{{*/ */ void TransactionStageRemoval(Item *I, const std::string &FinalFile); + /** \brief Get the full pathname of the final file for the current URI */ + virtual std::string GetFinalFilename() const; + pkgAcqMetaBase(pkgAcquire *Owner, const std::vector* IndexTargets, indexRecords* MetaIndexParser, @@ -495,50 +497,6 @@ class pkgAcqMetaBase : public pkgAcquire::Item /*{{{*/ pkgAcqMetaBase *TransactionManager=NULL); }; /*}}}*/ -/** \brief An acquire item that downloads the detached signature {{{ - * of a meta-index (Release) file, then queues up the release - * file itself. - * - * \todo Why protected members? - * - * \sa pkgAcqMetaIndex - */ -class APT_HIDDEN pkgAcqMetaSig : public pkgAcqMetaBase -{ - void *d; - - protected: - - /** \brief The file we need to verify */ - std::string MetaIndexFile; - - /** \brief The file we use to verify the MetaIndexFile with */ - std::string MetaIndexFileSignature; - - /** \brief Long URI description used in the acquire system */ - std::string URIDesc; - - /** \brief Short URI description used in the acquire system */ - std::string ShortDesc; - - 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); - - /** \brief Create a new pkgAcqMetaSig. */ - pkgAcqMetaSig(pkgAcquire *Owner, - pkgAcqMetaBase *TransactionManager, - std::string URI,std::string URIDesc, std::string ShortDesc, - std::string MetaIndexFile, - const std::vector* IndexTargets, - indexRecords* MetaIndexParser); - virtual ~pkgAcqMetaSig(); -}; - /*}}}*/ /** \brief An item that is responsible for downloading the meta-index {{{ * file (i.e., Release) itself and verifying its signature. * @@ -584,6 +542,53 @@ class APT_HIDDEN pkgAcqMetaIndex : public pkgAcqMetaBase std::string MetaIndexSigURI, std::string MetaIndexSigURIDesc, std::string MetaIndexSigShortDesc, const std::vector* IndexTargets, indexRecords* MetaIndexParser); + + friend class pkgAcqMetaSig; +}; + /*}}}*/ +/** \brief An acquire item that downloads the detached signature {{{ + * of a meta-index (Release) file, then queues up the release + * file itself. + * + * \todo Why protected members? + * + * \sa pkgAcqMetaIndex + */ +class APT_HIDDEN pkgAcqMetaSig : public pkgAcquire::Item +{ + void *d; + + pkgAcqMetaIndex * const MetaIndex; + + /** \brief The file we use to verify the MetaIndexFile with (not always set!) */ + std::string MetaIndexFileSignature; + + 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; + + public: + virtual std::string DescURI() {return RealURI;}; + + // 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); + + /** \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); + virtual ~pkgAcqMetaSig(); }; /*}}}*/ /** \brief An item repsonsible for downloading clearsigned metaindexes {{{*/ diff --git a/apt-pkg/indexrecords.cc b/apt-pkg/indexrecords.cc index d65266f64..de2617833 100644 --- a/apt-pkg/indexrecords.cc +++ b/apt-pkg/indexrecords.cc @@ -58,6 +58,11 @@ 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::const_iterator sum = Entries.find(MetaKey); @@ -133,9 +138,15 @@ bool indexRecords::Load(const string Filename) /*{{{*/ return false; } - string Label = Section.FindS("Label"); - string StrDate = Section.FindS("Date"); - string StrValidUntil = Section.FindS("Valid-Until"); + 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) @@ -158,20 +169,13 @@ bool indexRecords::Load(const string Filename) /*{{{*/ (MinAge == 0 || ValidUntil == 0)) // No user settings, use the one from the Release file return true; - time_t date; - if (RFC1123StrToTime(StrDate.c_str(), date) == false) - { - strprintf(ErrorText, _("Invalid 'Date' entry in Release file %s"), Filename.c_str()); - return false; - } - if (MinAge != 0 && ValidUntil != 0) { - time_t const min_date = date + MinAge; + time_t const min_date = Date + MinAge; if (ValidUntil < min_date) ValidUntil = min_date; } if (MaxAge != 0) { - time_t const max_date = date + MaxAge; + time_t const max_date = Date + MaxAge; if (ValidUntil == 0 || ValidUntil > max_date) ValidUntil = max_date; } diff --git a/apt-pkg/indexrecords.h b/apt-pkg/indexrecords.h index 35e534c12..6ed5f0c2b 100644 --- a/apt-pkg/indexrecords.h +++ b/apt-pkg/indexrecords.h @@ -36,6 +36,7 @@ class indexRecords std::string Dist; std::string Suite; std::string ExpectedDist; + time_t Date; time_t ValidUntil; bool SupportsAcquireByHash; @@ -62,6 +63,7 @@ class indexRecords 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 */ -- cgit v1.2.3 From 314b47542c57d0a12c55dd1dd334cf233a33fcfb Mon Sep 17 00:00:00 2001 From: Helmut Grohne Date: Mon, 9 Mar 2015 18:11:10 +0100 Subject: parse arch-qualified Provides correctly The underlying problem is that libapt-pkg does not correctly parse these provides. Internally, it creates a version named "baz:i386" with architecture amd64. Of course, such a package name is invalid and thus this version is completely inaccessible. Thus, this bug should not cause apt to accept a broken situation as valid. Nevertheless, it prevents using architecture qualified depends. Closes: 777071 --- apt-pkg/deb/deblistparser.cc | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 4eef66c2b..3941cf2f2 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -817,10 +817,16 @@ bool debListParser::ParseProvides(pkgCache::VerIterator &Ver) while (1) { Start = ParseDepends(Start,Stop,Package,Version,Op); + const size_t archfound = Package.rfind(':'); if (Start == 0) return _error->Error("Problem parsing Provides line"); if (Op != pkgCache::Dep::NoOp && Op != pkgCache::Dep::Equals) { _error->Warning("Ignoring Provides line with non-equal DepCompareOp for package %s", Package.c_str()); + } 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) + return false; } else if ((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign) { if (NewProvidesAllArch(Ver, Package, Version) == false) return false; -- cgit v1.2.3 From 58702f8563a443a7c6e66253b259c2488b877290 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 19 May 2015 10:40:55 +0200 Subject: don't try other compressions on hashsum mismatch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we e.g. fail on hash verification for Packages.xz its highly unlikely that it will be any better with Packages.gz, so we just waste download bandwidth and time. It also causes us always to fallback to the uncompressed Packages file for which the error will finally be reported, which in turn confuses users as the file usually doesn't exist on the mirrors, so a bug in apt is suspected for even trying it… --- apt-pkg/acquire-item.cc | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 8155b9bfe..cf89717c4 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -154,7 +154,18 @@ 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(); } @@ -167,7 +178,7 @@ void pkgAcquire::Item::Failed(string Message,pkgAcquire::MethodConfig *Cnf) RenameOnError(MaximumSizeExceeded); // 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); @@ -1403,17 +1414,19 @@ void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *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; + size_t const nextExt = CompressionExtensions.find(' '); + if (nextExt != std::string::npos) + { + CompressionExtensions = CompressionExtensions.substr(nextExt+1); + Init(RealURI, Desc.Description, Desc.ShortDesc); + Status = StatIdle; + return; + } } - Item::Failed(Message,Cnf); - if(Target->IsOptional() && ExpectedHashes.empty() && Stage == STAGE_DOWNLOAD) Status = StatDone; else -- cgit v1.2.3 From 448c38bdcd72b52f11ec5f326f822cf57653f81c Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 6 Jun 2015 12:28:00 +0200 Subject: rework hashsum verification in the acquire system MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Having every item having its own code to verify the file(s) it handles is an errorprune process and easy to break, especially if items move through various stages (download, uncompress, patching, …). With a giant rework we centralize (most of) the verification to have a better enforcement rate and (hopefully) less chance for bugs, but it breaks the ABI bigtime in exchange – and as we break it anyway, it is broken even harder. It shouldn't effect most frontends as they don't deal with the acquire system at all or implement their own items, but some do and will need to be patched (might be an opportunity to use apt on-board material). The theory is simple: Items implement methods to decide if hashes need to be checked (in this stage) and to return the expected hashes for this item (in this stage). The verification itself is done in worker message passing which has the benefit that a hashsum error is now a proper error for the acquire system rather than a Done() which is later revised to a Failed(). --- apt-pkg/acquire-item.cc | 3750 +++++++++++++++++++++---------------------- apt-pkg/acquire-item.h | 677 ++++---- apt-pkg/acquire-method.cc | 5 +- apt-pkg/acquire-worker.cc | 189 ++- apt-pkg/contrib/hashes.cc | 10 + apt-pkg/contrib/hashes.h | 9 + apt-pkg/deb/debindexfile.cc | 4 +- apt-pkg/deb/debmetaindex.cc | 78 +- apt-pkg/indexrecords.cc | 2 +- apt-pkg/pkgcache.h | 7 +- 10 files changed, 2319 insertions(+), 2412 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index cf89717c4..ec6ec6e84 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -107,36 +107,296 @@ static bool AllowInsecureRepositories(indexRecords const * const MetaIndexParser } /*}}}*/ +// 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; +} +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 +{ + /* FIXME: We have only hashes for uncompressed pdiffs. + rred uncompresses them on the fly while parsing. + In StateFetchDiff state we also uncompress on the fly for hash check. + Hashes are checked while searching for (next) patch to apply. */ + return false; +} +HashStringList pkgAcqIndexDiffs::GetExpectedHashes() const +{ + 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 */ + return State == StateApplyDiff; +} +HashStringList pkgAcqIndexMergeDiffs::GetExpectedHashes() const +{ + 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->URI, 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(DataTarget.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; +} + /*}}}*/ // 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), Complete(false), Local(false), + QueueCounter(0), ExpectedAdditionalItems(0), Owner(Owner) { 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 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"); @@ -169,59 +429,28 @@ void pkgAcquire::Item::Failed(string Message,pkgAcquire::MethodConfig *Cnf) 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.empty() == false) + 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(); @@ -230,22 +459,24 @@ void pkgAcquire::Item::Start(string /*Message*/,unsigned long long Size) } /*}}}*/ // Acquire::Item::Done - Item downloaded OK /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void pkgAcquire::Item::Done(string Message,unsigned long long Size,HashStringList const &/*Hash*/, - pkgAcquire::MethodConfig * /*Cnf*/) +void pkgAcquire::Item::Done(string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const /*Cnf*/) { // We just downloaded something.. string FileName = LookupTag(Message,"Filename"); UsedMirror = LookupTag(Message,"UsedMirror"); - if (Complete == false && !Local && FileName == DestFile) + unsigned long long const downloadedSize = Hashes.FileSize(); + if (downloadedSize != 0) { - if (Owner->Log != 0) - Owner->Log->Fetched(Size,atoi(LookupTag(Message,"Resume-Point","0").c_str())); - } + if (Complete == false && !Local && FileName == DestFile) + { + if (Owner->Log != 0) + Owner->Log->Fetched(Hashes.FileSize(),atoi(LookupTag(Message,"Resume-Point","0").c_str())); + } - if (FileSize == 0) - FileSize= Size; + if (FileSize == 0) + FileSize= downloadedSize; + } Status = StatDone; ErrorText = string(); Owner->Dequeue(this); @@ -255,7 +486,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; @@ -271,76 +502,40 @@ 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) +void pkgAcquire::Item::Dequeue() /*{{{*/ { - 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; + Owner->Dequeue(this); } -/* 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); -} - /*}}}*/ -bool pkgAcquire::Item::RenameOnError(pkgAcquire::Item::RenameOnErrorState const error)/*{{{*/ + /*}}}*/ +bool pkgAcquire::Item::RenameOnError(pkgAcquire::Item::RenameOnErrorState const error)/*{{{*/ { 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"); + errtext = _("Does not start with a cleartext signature"); Status = StatError; break; case MaximumSizeExceeded: @@ -351,6 +546,8 @@ bool pkgAcquire::Item::RenameOnError(pkgAcquire::Item::RenameOnErrorState const // no handling here, done by callers break; } + if (ErrorText.empty()) + ErrorText = errtext; return false; } /*}}}*/ @@ -360,15 +557,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()) @@ -411,2083 +601,1897 @@ void pkgAcquire::Item::ReportMirrorFailure(string FailCode) } } /*}}}*/ -// AcqDiffIndex::AcqDiffIndex - Constructor /*{{{*/ -// --------------------------------------------------------------------- -/* Get the DiffIndex file first and see if there are patches available - * If so, create a pkgAcqIndexDiffs fetcher that will get and apply the - * 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) +std::string pkgAcquire::Item::HashSum() const /*{{{*/ { - - 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"; - - DestFile = GetPartialFileNameFromURI(Desc.URI); + HashStringList const hashes = GetExpectedHashes(); + HashString const * const hs = hashes.find(NULL); + return hs != NULL ? hs->toStr() : ""; +} + /*}}}*/ - if(Debug) - std::clog << "pkgAcqDiffIndex: " << Desc.URI << std::endl; +pkgAcqTransactionItem::pkgAcqTransactionItem(pkgAcquire * const Owner, /*{{{*/ + pkgAcqMetaBase * const TransactionManager, IndexTarget const * const Target) : + pkgAcquire::Item(Owner), Target(Target), TransactionManager(TransactionManager) +{ + if (TransactionManager != this) + TransactionManager->Add(this); +} + /*}}}*/ +pkgAcqTransactionItem::~pkgAcqTransactionItem() /*{{{*/ +{ +} + /*}}}*/ +HashStringList pkgAcqTransactionItem::GetExpectedHashesFor(std::string const MetaKey) const /*{{{*/ +{ + if (TransactionManager->MetaIndexParser == NULL) + return HashStringList(); + indexRecords::checkSum * const R = TransactionManager->MetaIndexParser->Lookup(MetaKey); + if (R == NULL) + return HashStringList(); + return R->Hashes; +} + /*}}}*/ - // look for the current package file - CurrentPackagesFile = GetFinalFileNameFromURI(RealURI); +// AcqMetaBase - Constructor /*{{{*/ +pkgAcqMetaBase::pkgAcqMetaBase(pkgAcquire * const Owner, + pkgAcqMetaBase * const TransactionManager, + std::vector const * const IndexTargets, + IndexTarget const &DataTarget, + indexRecords * const MetaIndexParser) +: pkgAcqTransactionItem(Owner, TransactionManager, NULL), DataTarget(DataTarget), + MetaIndexParser(MetaIndexParser), LastMetaIndexParser(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; - // 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:/") + // ensure the toplevel is in error state too + for (std::vector::iterator I = Transaction.begin(); + I != Transaction.end(); ++I) { - // 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; + (*I)->TransactionState(TransactionAbort); } + Transaction.clear(); +} + /*}}}*/ +// AcqMetaBase::TransactionHasError - Check for errors in Transaction /*{{{*/ +APT_PURE bool pkgAcqMetaBase::TransactionHasError() const +{ + for (std::vector::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; - if(Debug) - std::clog << "pkgAcqDiffIndex::pkgAcqDiffIndex(): " - << CurrentPackagesFile << std::endl; - - QueueURI(Desc); - + // move new files into place *and* remove files that are not + // part of the transaction but are still on disk + for (std::vector::iterator I = Transaction.begin(); + I != Transaction.end(); ++I) + { + (*I)->TransactionState(TransactionCommit); + } + Transaction.clear(); } /*}}}*/ -// Acquire::Item::GetFinalFilename - Return the full final file path /*{{{*/ -std::string pkgAcqDiffIndex::GetFinalFilename() const +// AcqMetaBase::TransactionStageCopy - Stage a file for copying /*{{{*/ +void pkgAcqMetaBase::TransactionStageCopy(pkgAcqTransactionItem * const I, + const std::string &From, + const std::string &To) { - // the logic we inherent from pkgAcqBaseIndex isn't what we need here - return pkgAcquire::Item::GetFinalFilename(); + I->PartialFile = From; + I->DestFile = To; } /*}}}*/ -// AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/ +// 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\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; +} + /*}}}*/ +// AcqMetaBase::Custom600Headers - Get header for AcqMetaBase /*{{{*/ // --------------------------------------------------------------------- -/* 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 pkgAcqMetaBase::Custom600Headers() const { - string const Final = GetFinalFilename(); + std::string Header = "\nIndex-File: true"; + std::string MaximumSize; + strprintf(MaximumSize, "\nMaximum-Size: %i", + _config->FindI("Acquire::MaxReleaseFileSize", 10*1000*1000)); + Header += MaximumSize; - if(Debug) - std::clog << "Custom600Header-IMS: " << Final << std::endl; + string const FinalFile = GetFinalFilename(); struct stat Buf; - if (stat(Final.c_str(),&Buf) != 0) - return "\nIndex-File: true"; - - return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime); + if (stat(FinalFile.c_str(),&Buf) == 0) + Header += "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime); + + return Header; } /*}}}*/ -void pkgAcqDiffIndex::QueueOnIMSHit() const /*{{{*/ +// AcqMetaBase::QueueForSignatureVerify /*{{{*/ +void pkgAcqMetaBase::QueueForSignatureVerify(pkgAcqTransactionItem * const I, std::string const &File, std::string const &Signature) { - // 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); + AuthPass = true; + I->Desc.URI = "gpgv:" + Signature; + I->DestFile = File; + QueueURI(I->Desc); + I->SetActiveSubprocess("gpgv"); } /*}}}*/ -bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile) /*{{{*/ +// AcqMetaBase::CheckDownloadDone /*{{{*/ +bool pkgAcqMetaBase::CheckDownloadDone(pkgAcqTransactionItem * const I, const std::string &Message, HashStringList const &Hashes) const { - // failing here is fine: our caller will take care of trying to - // get the complete file if patching fails - if(Debug) - std::clog << "pkgAcqDiffIndex::ParseIndexDiff() " << IndexDiffFile - << std::endl; - - FileFd Fd(IndexDiffFile,FileFd::ReadOnly); - pkgTagFile TF(&Fd); - if (_error->PendingError() == true) - return false; - - pkgTagSection Tags; - if(unlikely(TF.Step(Tags) == false)) - return false; - - HashStringList ServerHashes; - unsigned long long ServerSize = 0; + // We have just finished downloading a Release file (it is not + // verified yet) - for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type) + string const FileName = LookupTag(Message,"Filename"); + if (FileName.empty() == true) { - std::string tagname = *type; - tagname.append("-Current"); - std::string const tmp = Tags.FindS(tagname.c_str()); - if (tmp.empty() == true) - continue; - - string hash; - unsigned long long size; - std::stringstream ss(tmp); - ss >> hash >> size; - if (unlikely(hash.empty() == true)) - continue; - if (unlikely(ServerSize != 0 && ServerSize != size)) - continue; - ServerHashes.push_back(HashString(*type, hash)); - ServerSize = size; + I->Status = StatError; + I->ErrorText = "Method gave a blank filename"; + return false; } - if (ServerHashes.usable() == false) + if (FileName != I->DestFile) { - if (Debug == true) - std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": Did not find a good hashsum in the index" << std::endl; + I->Local = true; + I->Desc.URI = "copy:" + FileName; + I->QueueURI(I->Desc); return false; } - if (ServerHashes != HashSums()) + // 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()) { - if (Debug == true) + // detect IMS-Hits servers haven't detected by Hash comparison + std::string const FinalFile = I->GetFinalFilename(); + if (RealFileExists(FinalFile) && Hashes.VerifyFile(FinalFile) == true) { - std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": Index has different hashes than parser, probably older, so fail pdiffing" << std::endl; - printHashSumComparision(CurrentPackagesFile, ServerHashes, HashSums()); + IMSHit = true; + unlink(I->DestFile.c_str()); } - return false; } - if (ServerHashes.VerifyFile(CurrentPackagesFile) == true) + if(IMSHit == true) { - // 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; - QueueOnIMSHit(); - return 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(); } - FileFd fd(CurrentPackagesFile, FileFd::ReadOnly); - Hashes LocalHashesCalc; - LocalHashesCalc.AddFD(fd); - HashStringList const LocalHashes = LocalHashesCalc.GetHashStringList(); + // set Item to complete as the remaining work is all local (verify etc) + I->Complete = true; - if(Debug) - std::clog << "Server-Current: " << ServerHashes.find(NULL)->toStr() << " and we start at " - << fd.Name() << " " << fd.FileSize() << " " << LocalHashes.find(NULL)->toStr() << std::endl; + 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 - // parse all of (provided) history - vector available_patches; - bool firstAcceptedHashes = true; - for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type) + if (TransactionManager->IMSHit == false) { - if (LocalHashes.find(*type) == NULL) - continue; - - std::string tagname = *type; - tagname.append("-History"); - 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); - - while (ss >> hash >> size >> filename) + // 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")) { - if (unlikely(hash.empty() == true || filename.empty() == true)) - continue; - - // see if we have a record for this file already - std::vector::iterator cur = available_patches.begin(); - for (; cur != available_patches.end(); ++cur) - { - if (cur->file != filename || unlikely(cur->result_size != size)) - continue; - cur->result_hashes.push_back(HashString(*type, hash)); - break; - } - if (cur != available_patches.end()) - continue; - if (firstAcceptedHashes == true) - { - DiffInfo next; - next.file = filename; - next.result_hashes.push_back(HashString(*type, hash)); - next.result_size = size; - next.patch_size = 0; - available_patches.push_back(next); - } + 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 = new indexRecords; + _error->PushToStack(); + if (RealFileExists(FinalInRelease)) + TransactionManager->LastMetaIndexParser->Load(FinalInRelease); else + TransactionManager->LastMetaIndexParser->Load(FinalRelease); + // its unlikely to happen, but if what we have is bad ignore it + if (_error->PendingError()) { - if (Debug == true) - std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": File " << filename - << " wasn't in the list for the first parsed hash! (history)" << std::endl; - break; + delete TransactionManager->LastMetaIndexParser; + TransactionManager->LastMetaIndexParser = NULL; } + _error->RevertToStack(); } - firstAcceptedHashes = false; } - if (unlikely(available_patches.empty() == true)) + if (TransactionManager->MetaIndexParser->Load(DestFile) == false) { - if (Debug) - std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": " - << "Couldn't find any patches for the patch series." << std::endl; + Status = StatAuthError; + ErrorText = TransactionManager->MetaIndexParser->ErrorText; return false; } - for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type) + if (!VerifyVendor(Message)) { - if (LocalHashes.find(*type) == NULL) - continue; + Status = StatAuthError; + return false; + } - std::string tagname = *type; - tagname.append("-Patches"); - std::string const tmp = Tags.FindS(tagname.c_str()); - if (tmp.empty() == true) - continue; + if (_config->FindB("Debug::pkgAcquire::Auth", false)) + std::cerr << "Signature verification succeeded: " + << DestFile << std::endl; - string hash, filename; - unsigned long long size; - std::stringstream ss(tmp); + // Download further indexes with verification + QueueIndexes(true); - while (ss >> hash >> size >> filename) + return true; +} + /*}}}*/ +void pkgAcqMetaBase::QueueIndexes(bool const verify) /*{{{*/ +{ + // at this point the real Items are loaded in the fetcher + ExpectedAdditionalItems = 0; + + vector ::const_iterator Target; + for (Target = IndexTargets->begin(); + Target != IndexTargets->end(); + ++Target) + { + if (verify == true && TransactionManager->MetaIndexParser->Exists((*Target)->MetaKey) == false) { - if (unlikely(hash.empty() == true || filename.empty() == true)) + // optional target that we do not have in the Release file are skipped + if ((*Target)->IsOptional()) continue; - // see if we have a record for this file already - std::vector::iterator cur = available_patches.begin(); - for (; cur != available_patches.end(); ++cur) - { - if (cur->file != filename) - continue; - if (unlikely(cur->patch_size != 0 && cur->patch_size != size)) - continue; - cur->patch_hashes.push_back(HashString(*type, hash)); - cur->patch_size = size; - 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! (patches)" << std::endl; - break; + 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; } + + /* 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 || + TransactionManager->MetaIndexParser->Exists((*Target)->MetaKey + ".diff/Index") == true)) + new pkgAcqDiffIndex(Owner, TransactionManager, *Target); + else + new pkgAcqIndex(Owner, TransactionManager, *Target); } +} + /*}}}*/ +bool pkgAcqMetaBase::VerifyVendor(string const &Message) /*{{{*/ +{ + string::size_type pos; - bool foundStart = false; - for (std::vector::iterator cur = available_patches.begin(); - cur != available_patches.end(); ++cur) + // 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) { - if (LocalHashes != cur->result_hashes) - continue; - - available_patches.erase(available_patches.begin(), cur); - foundStart = true; - break; + 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()); - if (foundStart == false || unlikely(available_patches.empty() == true)) + string Transformed = TransactionManager->MetaIndexParser->GetExpectedDist(); + + if (Transformed == "../project/experimental") { - if (Debug) - std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": " - << "Couldn't find the start of the patch series." << std::endl; - return false; + Transformed = "experimental"; } - // patching with too many files is rather slow compared to a fast download - unsigned long const fileLimit = _config->FindI("Acquire::PDiffs::FileLimit", 0); - if (fileLimit != 0 && fileLimit < available_patches.size()) + pos = Transformed.rfind('/'); + if (pos != string::npos) { - if (Debug) - std::clog << "Need " << available_patches.size() << " diffs (Limit is " << fileLimit - << ") so fallback to complete download" << std::endl; - return false; + Transformed = Transformed.substr(0, pos); } - // calculate the size of all patches we have to get - // note that all sizes are uncompressed, while we download compressed files - unsigned long long patchesSize = 0; - for (std::vector::const_iterator cur = available_patches.begin(); - cur != available_patches.end(); ++cur) - patchesSize += cur->patch_size; - unsigned long long const sizeLimit = ServerSize * _config->FindI("Acquire::PDiffs::SizeLimit", 100); - if (sizeLimit > 0 && (sizeLimit/100) < patchesSize) + if (Transformed == ".") { - if (Debug) - std::clog << "Need " << patchesSize << " bytes (Limit is " << sizeLimit/100 - << ") so fallback to complete download" << std::endl; - return false; + Transformed = ""; } - // we have something, queue the diffs - string::size_type const last_space = Description.rfind(" "); - if(last_space != string::npos) - Description.erase(last_space, Description.size()-last_space); + if (_config->FindB("Acquire::Check-Valid-Until", true) == true && + TransactionManager->MetaIndexParser->GetValidUntil() > 0) { + time_t const invalid_since = time(NULL) - TransactionManager->MetaIndexParser->GetValidUntil(); + if (invalid_since > 0) + { + std::string errmsg; + strprintf(errmsg, + // TRANSLATOR: The first %s is the URL of the bad Release file, the second is + // the time since then the file is invalid - formated in the same way as in + // the download progress display (e.g. 7d 3h 42min 1s) + _("Release file for %s is expired (invalid since %s). " + "Updates for this repository will not be applied."), + DataTarget.URI.c_str(), TimeToStr(invalid_since).c_str()); + if (ErrorText.empty()) + ErrorText = errmsg; + return _error->Error("%s", errmsg.c_str()); + } + } - /* decide if we should download patches one by one or in one go: - The first is good if the server merges patches, but many don't so client - based merging can be attempt in which case the second is better. - "bad things" will happen if patches are merged on the server, - but client side merging is attempt as well */ - bool pdiff_merge = _config->FindB("Acquire::PDiffs::Merge", true); - if (pdiff_merge == true) + /* 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()) { - // reprepro adds this flag if it has merged patches on the server - std::string const precedence = Tags.FindS("X-Patch-Precedence"); - pdiff_merge = (precedence != "merged"); + TransactionManager->IMSHit = true; + unlink(DestFile.c_str()); + PartialFile = DestFile = GetFinalFilename(); + delete TransactionManager->MetaIndexParser; + TransactionManager->MetaIndexParser = TransactionManager->LastMetaIndexParser; + TransactionManager->LastMetaIndexParser = NULL; } - if (pdiff_merge == false) + if (_config->FindB("Debug::pkgAcquire::Auth", false)) { - new pkgAcqIndexDiffs(Owner, TransactionManager, Target, ExpectedHashes, - MetaIndexParser, available_patches); + std::cerr << "Got Codename: " << TransactionManager->MetaIndexParser->GetDist() << std::endl; + std::cerr << "Expecting Dist: " << TransactionManager->MetaIndexParser->GetExpectedDist() << std::endl; + std::cerr << "Transformed Dist: " << Transformed << std::endl; } - else + + if (TransactionManager->MetaIndexParser->CheckDist(Transformed) == false) { - std::vector *diffs = new std::vector(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); + // 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(), + TransactionManager->MetaIndexParser->GetDist().c_str()); + } } - Complete = false; - Status = StatDone; - Dequeue(); return true; } /*}}}*/ -void pkgAcqDiffIndex::Failed(string Message,pkgAcquire::MethodConfig * Cnf)/*{{{*/ -{ - Item::Failed(Message,Cnf); - Status = StatDone; - - if(Debug) - 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); +pkgAcqMetaClearSig::pkgAcqMetaClearSig(pkgAcquire * const Owner, /*{{{*/ + IndexTarget const &ClearsignedTarget, + IndexTarget const &DetachedDataTarget, IndexTarget const &DetachedSigTarget, + const vector* const IndexTargets, + indexRecords * const MetaIndexParser) : + pkgAcqMetaIndex(Owner, this, ClearsignedTarget, DetachedSigTarget, IndexTargets, MetaIndexParser), + ClearsignedTarget(ClearsignedTarget), + DetachedDataTarget(DetachedDataTarget), DetachedSigTarget(DetachedSigTarget) +{ + // index targets + (worst case:) Release/Release.gpg + ExpectedAdditionalItems = IndexTargets->size() + 2; + TransactionManager->Add(this); } /*}}}*/ -bool pkgAcqDiffIndex::TransactionState(TransactionStates const state) /*{{{*/ +pkgAcqMetaClearSig::~pkgAcqMetaClearSig() /*{{{*/ { - 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; } /*}}}*/ -void pkgAcqDiffIndex::Done(string Message,unsigned long long Size,HashStringList const &Hashes, /*{{{*/ - pkgAcquire::MethodConfig *Cnf) +// pkgAcqMetaClearSig::Custom600Headers - Insert custom request headers /*{{{*/ +string pkgAcqMetaClearSig::Custom600Headers() const { - if(Debug) - std::clog << "pkgAcqDiffIndex::Done(): " << Desc.URI << std::endl; - - Item::Done(Message, Size, Hashes, Cnf); + string Header = pkgAcqMetaBase::Custom600Headers(); + Header += "\nFail-Ignore: true"; + return Header; +} + /*}}}*/ +// pkgAcqMetaClearSig::Done - We got a file /*{{{*/ +class APT_HIDDEN DummyItem : public pkgAcquire::Item +{ + IndexTarget const * const Target; + public: + virtual std::string DescURI() const {return Target->URI;}; + virtual HashStringList GetExpectedHashes() const {return HashStringList();}; - // verify the index target - if(Target && Target->MetaKey != "" && MetaIndexParser && Hashes.usable()) + DummyItem(pkgAcquire * const Owner, IndexTarget const * const Target) : + pkgAcquire::Item(Owner), Target(Target) { - 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; - } - + Status = StatDone; + DestFile = GetFinalFileNameFromURI(Target->URI); } +}; +void pkgAcqMetaClearSig::Done(std::string const &Message, + HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cnf) +{ + Item::Done(Message, Hashes, Cnf); - string const FinalFile = GetFinalFilename(); - if(StringToBool(LookupTag(Message,"IMS-Hit"),false)) - DestFile = FinalFile; - - if(ParseDiffIndex(DestFile) == false) + // 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)) { - Failed("Message: Couldn't parse pdiff index", Cnf); - // queue for final move - this should happen even if we fail - // while parsing (e.g. on sizelimit) and download the complete file. - TransactionManager->TransactionStageCopy(this, DestFile, FinalFile); + pkgAcquire::Item::Failed(Message, Cnf); + RenameOnError(NotClearsigned); + TransactionManager->AbortTransaction(); return; } - TransactionManager->TransactionStageCopy(this, DestFile, FinalFile); - - Complete = true; - Status = StatDone; - Dequeue(); - - 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, &DetachedDataTarget); + new DummyItem(Owner, &DetachedSigTarget); + } + } } /*}}}*/ -// 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 diffs) - : pkgAcqBaseIndex(Owner, TransactionManager, Target, ExpectedHashes, MetaIndexParser), - available_patches(diffs) +void pkgAcqMetaClearSig::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf) /*{{{*/ { - DestFile = GetPartialFileNameFromURI(Target->URI); - - Debug = _config->FindB("Debug::pkgAcquire::Diffs",false); + Item::Failed(Message, Cnf); - RealURI = Target->URI; - Desc.Owner = this; - Description = Target->Description; - Desc.ShortDesc = Target->ShortDesc; + // we failed, we will not get additional items from this method + ExpectedAdditionalItems = 0; - if(available_patches.empty() == true) + if (AuthPass == false) { - // we are done (yeah!), check hashes against the final file - DestFile = GetFinalFileNameFromURI(Target->URI); - Finish(true); + // Queue the 'old' InRelease file for removal if we try Release.gpg + // as otherwise the file will stay around and gives a false-auth + // impression (CVE-2012-0214) + TransactionManager->TransactionStageRemoval(this, GetFinalFilename()); + Status = StatDone; + + new pkgAcqMetaIndex(Owner, TransactionManager, DetachedDataTarget, DetachedSigTarget, IndexTargets, TransactionManager->MetaIndexParser); } else { - // patching needs to be bootstrapped with the 'old' version - std::string const PartialFile = GetPartialFileNameFromURI(RealURI); - if (RealFileExists(PartialFile) == false) + 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) { - if (symlink(GetFinalFilename().c_str(), PartialFile.c_str()) != 0) + 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)) { - Failed("Link creation of " + PartialFile + " to " + GetFinalFilename() + " failed", NULL); - return; + // open the last Release if we have it + if (TransactionManager->IMSHit == false) + { + TransactionManager->LastMetaIndexParser = new indexRecords; + _error->PushToStack(); + if (RealFileExists(FinalInRelease)) + TransactionManager->LastMetaIndexParser->Load(FinalInRelease); + else + TransactionManager->LastMetaIndexParser->Load(FinalRelease); + // its unlikely to happen, but if what we have is bad ignore it + if (_error->PendingError()) + { + delete TransactionManager->LastMetaIndexParser; + TransactionManager->LastMetaIndexParser = NULL; + } + _error->RevertToStack(); + } } - } - // get the next diff - State = StateFetchDiff; - QueueNextDiff(); + // we parse the indexes here because at this point the user wanted + // a repository that may potentially harm him + if (TransactionManager->MetaIndexParser->Load(PartialRelease) == false || VerifyVendor(Message) == false) + /* expired Release files are still a problem you need extra force for */; + else + QueueIndexes(true); + } } } /*}}}*/ -void pkgAcqIndexDiffs::Failed(string Message,pkgAcquire::MethodConfig * Cnf)/*{{{*/ -{ - Item::Failed(Message,Cnf); - Status = StatDone; - 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); - RenameOnError(PDiffError); - new pkgAcqIndex(Owner, TransactionManager, Target, ExpectedHashes, MetaIndexParser); - Finish(); -} - /*}}}*/ -// Finish - helper that cleans the item out of the fetcher queue /*{{{*/ -void pkgAcqIndexDiffs::Finish(bool allDone) +pkgAcqMetaIndex::pkgAcqMetaIndex(pkgAcquire * const Owner, /*{{{*/ + pkgAcqMetaBase * const TransactionManager, + IndexTarget const &DataTarget, + IndexTarget const &DetachedSigTarget, + vector const * const IndexTargets, + indexRecords * const MetaIndexParser) : + pkgAcqMetaBase(Owner, TransactionManager, IndexTargets, DataTarget, MetaIndexParser), + DetachedSigTarget(DetachedSigTarget) { - if(Debug) - std::clog << "pkgAcqIndexDiffs::Finish(): " - << allDone << " " - << Desc.URI << std::endl; - - // we restore the original name, this is required, otherwise - // the file will be cleaned - if(allDone) - { - if(HashSums().usable() && !HashSums().VerifyFile(DestFile)) - { - RenameOnError(HashSumMismatch); - Dequeue(); - return; - } + if(_config->FindB("Debug::Acquire::Transaction", false) == true) + std::clog << "New pkgAcqMetaIndex with TransactionManager " + << this->TransactionManager << std::endl; - TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename()); + DestFile = GetPartialFileNameFromURI(DataTarget.URI); - // this is for the "real" finish - Complete = true; - Status = StatDone; - Dequeue(); - if(Debug) - std::clog << "\n\nallDone: " << DestFile << "\n" << std::endl; - return; - } + // Create the item + Desc.Description = DataTarget.Description; + Desc.Owner = this; + Desc.ShortDesc = DataTarget.ShortDesc; + Desc.URI = DataTarget.URI; - if(Debug) - std::clog << "Finishing: " << Desc.URI << std::endl; - Complete = false; - Status = StatDone; - Dequeue(); - return; + // we expect more item + ExpectedAdditionalItems = IndexTargets->size(); + QueueURI(Desc); } /*}}}*/ -bool pkgAcqIndexDiffs::QueueNextDiff() /*{{{*/ +void pkgAcqMetaIndex::Done(string const &Message, /*{{{*/ + HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cfg) { - // calc sha1 of the just patched file - std::string const FinalFile = GetPartialFileNameFromURI(RealURI); + Item::Done(Message,Hashes,Cfg); - if(!FileExists(FinalFile)) + if(CheckDownloadDone(this, Message, Hashes)) { - Failed("Message: No FinalFile " + FinalFile + " available", NULL); - return false; + // 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; - FileFd fd(FinalFile, FileFd::ReadOnly); - Hashes LocalHashesCalc; - LocalHashesCalc.AddFD(fd); - HashStringList const LocalHashes = LocalHashesCalc.GetHashStringList(); - - if(Debug) - std::clog << "QueueNextDiff: " << FinalFile << " (" << LocalHashes.find(NULL)->toStr() << ")" << std::endl; + _error->Warning(_("The repository '%s' does not have a Release file. " + "This is deprecated, please contact the owner of the " + "repository."), DataTarget.Description.c_str()); - if (unlikely(LocalHashes.usable() == false || ExpectedHashes.usable() == false)) + // 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) { - Failed("Local/Expected hashes are not usable", NULL); - return false; - } - + // ensure old Release files are removed + TransactionManager->TransactionStageRemoval(this, GetFinalFilename()); + delete TransactionManager->MetaIndexParser; + TransactionManager->MetaIndexParser = NULL; - // final file reached before all patches are applied - if(LocalHashes == ExpectedHashes) - { - Finish(true); - return true; - } - - // remove all patches until the next matching patch is found - // this requires the Index file to be ordered - for(vector::iterator I = available_patches.begin(); - available_patches.empty() == false && - I != available_patches.end() && - I->result_hashes != LocalHashes; - ++I) - { - available_patches.erase(I); + // queue without any kind of hashsum support + QueueIndexes(false); } +} + /*}}}*/ +void pkgAcqMetaIndex::Finished() /*{{{*/ +{ + if(_config->FindB("Debug::Acquire::Transaction", false) == true) + std::clog << "Finished: " << DestFile <TransactionHasError() == false) + TransactionManager->CommitTransaction(); +} + /*}}}*/ +std::string pkgAcqMetaIndex::DescURI() const /*{{{*/ +{ + return DataTarget.URI; +} + /*}}}*/ - // error checking and falling back if no patch was found - if(available_patches.empty() == true) - { - Failed("No patches left to reach target", NULL); - return false; - } +// AcqMetaSig::AcqMetaSig - Constructor /*{{{*/ +pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire * const Owner, + pkgAcqMetaBase * const TransactionManager, + IndexTarget const * const Target, + pkgAcqMetaIndex * const MetaIndex) : + pkgAcqTransactionItem(Owner, TransactionManager, Target), MetaIndex(MetaIndex) +{ + DestFile = GetPartialFileNameFromURI(Target->URI); - // queue the right diff - Desc.URI = RealURI + ".diff/" + available_patches[0].file + ".gz"; - Desc.Description = Description + " " + available_patches[0].file + string(".pdiff"); - DestFile = GetPartialFileNameFromURI(RealURI + ".diff/" + available_patches[0].file); + // 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()); - if(Debug) - std::clog << "pkgAcqIndexDiffs::QueueNextDiff(): " << Desc.URI << std::endl; + // set the TransactionManager + if(_config->FindB("Debug::Acquire::Transaction", false) == true) + std::clog << "New pkgAcqMetaSig with TransactionManager " + << TransactionManager << std::endl; - QueueURI(Desc); + // Create the item + Desc.Description = Target->Description; + Desc.Owner = this; + Desc.ShortDesc = Target->ShortDesc; + Desc.URI = Target->URI; - return true; + // 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); } /*}}}*/ -void pkgAcqIndexDiffs::Done(string Message,unsigned long long Size, HashStringList const &Hashes, /*{{{*/ - pkgAcquire::MethodConfig *Cnf) +pkgAcqMetaSig::~pkgAcqMetaSig() /*{{{*/ { - if(Debug) - std::clog << "pkgAcqIndexDiffs::Done(): " << Desc.URI << std::endl; - - Item::Done(Message, Size, Hashes, Cnf); - - // FIXME: verify this download too before feeding it to rred - std::string const FinalFile = GetPartialFileNameFromURI(RealURI); - - // success in downloading a diff, enter ApplyDiff state - if(State == StateFetchDiff) +} + /*}}}*/ +// 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) { - FileFd fd(DestFile, FileFd::ReadOnly, FileFd::Gzip); - class Hashes LocalHashesCalc; - LocalHashesCalc.AddFD(fd); - HashStringList const LocalHashes = LocalHashesCalc.GetHashStringList(); + DestFile = MetaIndexFileSignature; + MetaIndexFileSignature.clear(); + } + Item::Done(Message, Hashes, Cfg); - if (fd.Size() != available_patches[0].patch_size || - available_patches[0].patch_hashes != LocalHashes) + if(MetaIndex->AuthPass == false) + { + if(MetaIndex->CheckDownloadDone(this, Message, Hashes) == true) { - // patchfiles are dated, so bad indicates a bad download, so kill it - unlink(DestFile.c_str()); - Failed("Patch has Size/Hashsum mismatch", NULL); - return; + // 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); - // rred excepts the patch as $FinalFile.ed - Rename(DestFile,FinalFile+".ed"); + // check if we need to fail at this point + if (MetaIndex->AuthPass == true && MetaIndex->CheckStopAuthentication(this, Message)) + return; - if(Debug) - std::clog << "Sending to rred method: " << FinalFile << std::endl; + string const FinalRelease = MetaIndex->GetFinalFilename(); + string const FinalReleasegpg = GetFinalFilename(); + string const FinalInRelease = TransactionManager->GetFinalFilename(); - State = StateApplyDiff; - Local = true; - Desc.URI = "rred:" + FinalFile; - QueueURI(Desc); - SetActiveSubprocess("rred"); - return; - } + if (RealFileExists(FinalReleasegpg) || RealFileExists(FinalInRelease)) + { + std::string downgrade_msg; + strprintf(downgrade_msg, _("The repository '%s' is no longer signed."), + MetaIndex->DataTarget.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->DataTarget.Description.c_str()); + // ensures that a Release.gpg file in the lists/ is removed by the transaction + TransactionManager->TransactionStageRemoval(this, DestFile); - // success in download/apply a diff, queue next (if needed) - if(State == StateApplyDiff) + // only allow going further if the users explicitely wants it + if(AllowInsecureRepositories(TransactionManager->MetaIndexParser, TransactionManager, this) == true) { - // remove the just applied patch - available_patches.erase(available_patches.begin()); - unlink((FinalFile + ".ed").c_str()); - - // move into place - if(Debug) + if (RealFileExists(FinalReleasegpg) || RealFileExists(FinalInRelease)) { - std::clog << "Moving patched file in place: " << std::endl - << DestFile << " -> " << FinalFile << std::endl; + // open the last Release if we have it + if (TransactionManager->IMSHit == false) + { + TransactionManager->LastMetaIndexParser = new indexRecords; + _error->PushToStack(); + if (RealFileExists(FinalInRelease)) + TransactionManager->LastMetaIndexParser->Load(FinalInRelease); + else + TransactionManager->LastMetaIndexParser->Load(FinalRelease); + // its unlikely to happen, but if what we have is bad ignore it + if (_error->PendingError()) + { + delete TransactionManager->LastMetaIndexParser; + TransactionManager->LastMetaIndexParser = NULL; + } + _error->RevertToStack(); + } } - Rename(DestFile,FinalFile); - chmod(FinalFile.c_str(),0644); - // see if there is more to download - if(available_patches.empty() == false) { - new pkgAcqIndexDiffs(Owner, TransactionManager, Target, - ExpectedHashes, MetaIndexParser, - available_patches); - return Finish(); - } else - // update - DestFile = FinalFile; - return Finish(true); + // we parse the indexes here because at this point the user wanted + // a repository that may potentially harm him + if (TransactionManager->MetaIndexParser->Load(MetaIndex->DestFile) == false || MetaIndex->VerifyVendor(Message) == false) + /* 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; } } /*}}}*/ -// AcqIndexMergeDiffs::AcqIndexMergeDiffs - Constructor /*{{{*/ -pkgAcqIndexMergeDiffs::pkgAcqIndexMergeDiffs(pkgAcquire *Owner, - pkgAcqMetaBase *TransactionManager, - struct IndexTarget const * const Target, - HashStringList const &ExpectedHashes, - indexRecords *MetaIndexParser, - DiffInfo const &patch, - std::vector const * const allPatches) - : pkgAcqBaseIndex(Owner, TransactionManager, Target, ExpectedHashes, MetaIndexParser), - patch(patch), allPatches(allPatches), State(StateFetchDiff) + + +// AcqBaseIndex - Constructor /*{{{*/ +pkgAcqBaseIndex::pkgAcqBaseIndex(pkgAcquire * const Owner, + pkgAcqMetaBase * const TransactionManager, + IndexTarget const * const Target) +: pkgAcqTransactionItem(Owner, TransactionManager, Target) +{ +} + /*}}}*/ + +// AcqDiffIndex::AcqDiffIndex - Constructor /*{{{*/ +// --------------------------------------------------------------------- +/* Get the DiffIndex file first and see if there are patches available + * If so, create a pkgAcqIndexDiffs fetcher that will get and apply the + * patches. If anything goes wrong in that process, it will fall back to + * the original packages file + */ +pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire * const Owner, + pkgAcqMetaBase * const TransactionManager, + IndexTarget const * const Target) + : pkgAcqBaseIndex(Owner, TransactionManager, Target) { Debug = _config->FindB("Debug::pkgAcquire::Diffs",false); - RealURI = Target->URI; Desc.Owner = this; - Description = Target->Description; + Desc.Description = Target->Description + ".diff/Index"; Desc.ShortDesc = Target->ShortDesc; + Desc.URI = Target->URI + ".diff/Index"; - Desc.URI = RealURI + ".diff/" + patch.file + ".gz"; - Desc.Description = Description + " " + patch.file + string(".pdiff"); + DestFile = GetPartialFileNameFromURI(Desc.URI); + + if(Debug) + std::clog << "pkgAcqDiffIndex: " << Desc.URI << std::endl; - DestFile = GetPartialFileNameFromURI(RealURI + ".diff/" + patch.file); + // look for the current package file + CurrentPackagesFile = GetFinalFileNameFromURI(Target->URI); + + // 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 << "pkgAcqIndexMergeDiffs: " << Desc.URI << std::endl; + std::clog << "pkgAcqDiffIndex::pkgAcqDiffIndex(): " + << CurrentPackagesFile << std::endl; QueueURI(Desc); + } /*}}}*/ -void pkgAcqIndexMergeDiffs::Failed(string Message,pkgAcquire::MethodConfig * Cnf)/*{{{*/ +// AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/ +// --------------------------------------------------------------------- +/* The only header we use is the last-modified header. */ +string pkgAcqDiffIndex::Custom600Headers() const { - if(Debug) - std::clog << "pkgAcqIndexMergeDiffs failed: " << Desc.URI << " with " << Message << std::endl; - - Item::Failed(Message,Cnf); - Status = StatDone; + string const Final = GetFinalFilename(); - // check if we are the first to fail, otherwise we are done here - State = StateDoneDiff; - for (std::vector::const_iterator I = allPatches->begin(); - I != allPatches->end(); ++I) - if ((*I)->State == StateErrorDiff) - return; + if(Debug) + std::clog << "Custom600Header-IMS: " << Final << std::endl; - // first failure means we should fallback - State = StateErrorDiff; - if (Debug) - std::clog << "Falling back to normal index file acquire" << std::endl; - DestFile = GetPartialFileNameFromURI(Target->URI); - RenameOnError(PDiffError); - new pkgAcqIndex(Owner, TransactionManager, Target, ExpectedHashes, MetaIndexParser); + struct stat Buf; + if (stat(Final.c_str(),&Buf) != 0) + return "\nIndex-File: true"; + + 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); } /*}}}*/ -void pkgAcqIndexMergeDiffs::Done(string Message,unsigned long long Size,HashStringList const &Hashes, /*{{{*/ - pkgAcquire::MethodConfig *Cnf) +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 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); - - 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; - } + std::clog << "pkgAcqDiffIndex::ParseIndexDiff() " << IndexDiffFile + << std::endl; - // rred expects the patch as $FinalFile.ed.$patchname.gz - Rename(DestFile, FinalFile + ".ed." + patch.file + ".gz"); + FileFd Fd(IndexDiffFile,FileFd::ReadOnly); + pkgTagFile TF(&Fd); + if (_error->PendingError() == true) + return false; - // check if this is the last completed diff - State = StateDoneDiff; - for (std::vector::const_iterator I = allPatches->begin(); - I != allPatches->end(); ++I) - if ((*I)->State != StateDoneDiff) - { - if(Debug) - std::clog << "Not the last done diff in the batch: " << Desc.URI << std::endl; - return; - } + pkgTagSection Tags; + if(unlikely(TF.Step(Tags) == false)) + return false; - // this is the last completed diff, so we are ready to apply now - State = StateApplyDiff; + HashStringList ServerHashes; + unsigned long long ServerSize = 0; - // patching needs to be bootstrapped with the 'old' version - if (symlink(GetFinalFilename().c_str(), FinalFile.c_str()) != 0) - { - Failed("Link creation of " + FinalFile + " to " + GetFinalFilename() + " failed", NULL); - return; - } + for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type) + { + std::string tagname = *type; + tagname.append("-Current"); + std::string const tmp = Tags.FindS(tagname.c_str()); + if (tmp.empty() == true) + continue; - if(Debug) - std::clog << "Sending to rred method: " << FinalFile << std::endl; + string hash; + unsigned long long size; + std::stringstream ss(tmp); + ss >> hash >> size; + if (unlikely(hash.empty() == true)) + continue; + if (unlikely(ServerSize != 0 && ServerSize != size)) + continue; + ServerHashes.push_back(HashString(*type, hash)); + ServerSize = size; + } - Local = true; - Desc.URI = "rred:" + FinalFile; - QueueURI(Desc); - SetActiveSubprocess("rred"); - return; + if (ServerHashes.usable() == false) + { + if (Debug == true) + std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": Did not find a good hashsum in the index" << std::endl; + return false; } - // success in download/apply all diffs, clean up - else if (State == StateApplyDiff) + + HashStringList const TargetFileHashes = GetExpectedHashesFor(Target->MetaKey); + if (TargetFileHashes.usable() == false || ServerHashes != TargetFileHashes) { - // see if we really got the expected file - if(ExpectedHashes.usable() && ExpectedHashes != Hashes) + if (Debug == true) { - RenameOnError(HashSumMismatch); - return; + std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": Index has different hashes than parser, probably older, so fail pdiffing" << std::endl; + printHashSumComparision(CurrentPackagesFile, ServerHashes, TargetFileHashes); } + return false; + } - // move the result into place - std::string const Final = GetFinalFilename(); + if (ServerHashes.VerifyFile(CurrentPackagesFile) == true) + { + // we have the same sha1 as the server so we are done here if(Debug) - std::clog << "Queue patched file in place: " << std::endl - << DestFile << " -> " << Final << std::endl; + std::clog << "pkgAcqDiffIndex: Package file " << CurrentPackagesFile << " is up-to-date" << std::endl; + QueueOnIMSHit(); + return true; + } - // queue for copy by the transaction manager - TransactionManager->TransactionStageCopy(this, DestFile, Final); + FileFd fd(CurrentPackagesFile, FileFd::ReadOnly); + Hashes LocalHashesCalc; + LocalHashesCalc.AddFD(fd); + HashStringList const LocalHashes = LocalHashesCalc.GetHashStringList(); - // ensure the ed's are gone regardless of list-cleanup - for (std::vector::const_iterator I = allPatches->begin(); - I != allPatches->end(); ++I) - { - std::string const PartialFile = GetPartialFileNameFromURI(RealURI); - std::string patch = PartialFile + ".ed." + (*I)->patch.file + ".gz"; - unlink(patch.c_str()); - } - unlink(FinalFile.c_str()); + if(Debug) + std::clog << "Server-Current: " << ServerHashes.find(NULL)->toStr() << " and we start at " + << fd.Name() << " " << fd.FileSize() << " " << LocalHashes.find(NULL)->toStr() << std::endl; - // all set and done - Complete = true; - if(Debug) - std::clog << "allDone: " << DestFile << "\n" << std::endl; - } -} - /*}}}*/ -// 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) -{ - if(MetaKey != "" && Hashes.usable()) + // parse all of (provided) history + vector available_patches; + bool firstAcceptedHashes = true; + for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type) { - indexRecords::checkSum *Record = MetaIndexParser->Lookup(MetaKey); - if(Record && Record->Hashes.usable() && Hashes != Record->Hashes) - { - printHashSumComparision(RealURI, Record->Hashes, Hashes); - return false; - } - } - return true; -} - /*}}}*/ -// 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); + if (LocalHashes.find(*type) == NULL) + continue; - 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) -{ - RealURI = Target->URI; + std::string tagname = *type; + tagname.append("-History"); + std::string const tmp = Tags.FindS(tagname.c_str()); + if (tmp.empty() == true) + continue; - // autoselect the compression method - AutoSelectCompression(); - Init(Target->URI, Target->Description, Target->ShortDesc); + string hash, filename; + unsigned long long size; + std::stringstream ss(tmp); - if(_config->FindB("Debug::Acquire::Transaction", false) == true) - std::clog << "New pkgIndex with TransactionManager " - << TransactionManager << std::endl; -} - /*}}}*/ -// AcqIndex::AutoSelectCompression - Select compression /*{{{*/ -void pkgAcqIndex::AutoSelectCompression() -{ - std::vector types = APT::Configuration::getCompressionTypes(); - CompressionExtensions = ""; - if (ExpectedHashes.usable()) - { - for (std::vector::const_iterator t = types.begin(); - t != types.end(); ++t) + while (ss >> hash >> size >> filename) { - std::string CompressedMetaKey = string(Target->MetaKey).append(".").append(*t); - if (*t == "uncompressed" || - MetaIndexParser->Exists(CompressedMetaKey) == true) - CompressionExtensions.append(*t).append(" "); + if (unlikely(hash.empty() == true || filename.empty() == true)) + continue; + + // see if we have a record for this file already + std::vector::iterator cur = available_patches.begin(); + for (; cur != available_patches.end(); ++cur) + { + if (cur->file != filename || unlikely(cur->result_size != size)) + continue; + cur->result_hashes.push_back(HashString(*type, hash)); + break; + } + if (cur != available_patches.end()) + continue; + if (firstAcceptedHashes == true) + { + DiffInfo next; + next.file = filename; + next.result_hashes.push_back(HashString(*type, hash)); + next.result_size = size; + next.patch_size = 0; + available_patches.push_back(next); + } + else + { + if (Debug == true) + std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": File " << filename + << " wasn't in the list for the first parsed hash! (history)" << std::endl; + break; + } } + firstAcceptedHashes = false; } - else + + if (unlikely(available_patches.empty() == true)) { - for (std::vector::const_iterator t = types.begin(); t != types.end(); ++t) - CompressionExtensions.append(*t).append(" "); + if (Debug) + std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": " + << "Couldn't find any patches for the patch series." << std::endl; + return false; } - if (CompressionExtensions.empty() == false) - CompressionExtensions.erase(CompressionExtensions.end()-1); -} - /*}}}*/ -// AcqIndex::Init - defered Constructor /*{{{*/ -void pkgAcqIndex::Init(string const &URI, string const &URIDesc, - string const &ShortDesc) -{ - Stage = STAGE_DOWNLOAD; - - DestFile = GetPartialFileNameFromURI(URI); - CurrentCompressionExtension = CompressionExtensions.substr(0, CompressionExtensions.find(' ')); - if (CurrentCompressionExtension == "uncompressed") + for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type) { - Desc.URI = URI; - if(Target) - MetaKey = string(Target->MetaKey); - } - 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); - } - - Desc.Description = URIDesc; - Desc.Owner = this; - Desc.ShortDesc = ShortDesc; - - QueueURI(Desc); -} - /*}}}*/ -// AcqIndex::AdjustForByHash - modify URI for by-hash support /*{{{*/ -void pkgAcqIndex::InitByHashIfNeeded(const std::string MetaKey) -{ - // TODO: - // - (maybe?) add support for by-hash into the sources.list as flag - // - make apt-ftparchive generate the hashes (and expire?) - 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()) - { - indexRecords::checkSum *Record = MetaIndexParser->Lookup(MetaKey); - if(Record) - { - // 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("/"); - Desc.URI = Desc.URI.replace( - trailing_slash, - Desc.URI.substr(trailing_slash+1).size()+1, - ByHash); - } else { - _error->Warning( - "Fetching ByHash requested but can not find record for %s", - MetaKey.c_str()); - } - } -} - /*}}}*/ -// 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(); - - string msg = "\nIndex-File: true"; - struct stat Buf; - if (stat(Final.c_str(),&Buf) == 0) - msg += "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime); + if (LocalHashes.find(*type) == NULL) + continue; - if(Target->IsOptional()) - msg += "\nFail-Ignore: true"; + std::string tagname = *type; + tagname.append("-Patches"); + std::string const tmp = Tags.FindS(tagname.c_str()); + if (tmp.empty() == true) + continue; - return msg; -} - /*}}}*/ -// pkgAcqIndex::Failed - getting the indexfile failed /*{{{*/ -void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf) -{ - Item::Failed(Message,Cnf); + string hash, filename; + unsigned long long size; + std::stringstream ss(tmp); - // authorisation matches will not be fixed by other compression types - if (Status != StatAuthError) - { - size_t const nextExt = CompressionExtensions.find(' '); - if (nextExt != std::string::npos) + while (ss >> hash >> size >> filename) { - CompressionExtensions = CompressionExtensions.substr(nextExt+1); - Init(RealURI, Desc.Description, Desc.ShortDesc); - Status = StatIdle; - return; - } - } - - if(Target->IsOptional() && ExpectedHashes.empty() && Stage == STAGE_DOWNLOAD) - Status = StatDone; - else - TransactionManager->AbortTransaction(); -} - /*}}}*/ -bool pkgAcqIndex::TransactionState(TransactionStates const state) /*{{{*/ -{ - if (pkgAcquire::Item::TransactionState(state) == false) - return false; + if (unlikely(hash.empty() == true || filename.empty() == true)) + continue; - switch (state) - { - case TransactionAbort: - if (Stage == STAGE_DECOMPRESS_AND_VERIFY) + // see if we have a record for this file already + std::vector::iterator cur = available_patches.begin(); + for (; cur != available_patches.end(); ++cur) { - // keep the compressed file, but drop the decompressed - EraseFileName.clear(); - if (PartialFile.empty() == false && flExtension(PartialFile) == "decomp") - unlink(PartialFile.c_str()); + if (cur->file != filename) + continue; + if (unlikely(cur->patch_size != 0 && cur->patch_size != size)) + continue; + cur->patch_hashes.push_back(HashString(*type, hash)); + cur->patch_size = size; + 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! (patches)" << std::endl; 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); - - // copy FinalFile into partial/ so that we check the hash again - string FinalFile = GetFinalFilename(); - Stage = STAGE_DECOMPRESS_AND_VERIFY; - Desc.URI = "copy:" + FinalFile; - 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 - method could possibly return an alternate filename which points - 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, - HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cfg) -{ - Item::Done(Message,Size,Hashes,Cfg); - - switch(Stage) - { - case STAGE_DOWNLOAD: - StageDownloadDone(Message, Hashes, Cfg); - break; - case STAGE_DECOMPRESS_AND_VERIFY: - StageDecompressDone(Message, Hashes, Cfg); - break; - } -} - /*}}}*/ -// AcqIndex::StageDownloadDone - Queue for decompress and verify /*{{{*/ -void pkgAcqIndex::StageDownloadDone(string Message, - HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cfg) -{ - // 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"); - if (FileName.empty() == false) - { - Stage = STAGE_DECOMPRESS_AND_VERIFY; - Local = true; - DestFile += ".decomp"; - Desc.URI = "copy:" + FileName; - QueueURI(Desc); - 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) - Local = true; - else - EraseFileName = FileName; - - // we need to verify the file against the current Release file again - // on if-modfied-since hit to avoid a stale attack against us - if(StringToBool(LookupTag(Message,"IMS-Hit"),false) == true) - { - // The files timestamp matches, reverify by copy into partial/ - EraseFileName = ""; - ReverifyAfterIMS(); - return; - } - - // If we have compressed indexes enabled, queue for hash verification - if (_config->FindB("Acquire::GzipIndexes",false)) - { - DestFile = GetPartialFileNameFromURI(RealURI + '.' + CurrentCompressionExtension); - EraseFileName = ""; - Stage = STAGE_DECOMPRESS_AND_VERIFY; - Desc.URI = "copy:" + FileName; - QueueURI(Desc); - SetActiveSubprocess("copy"); - return; - } - - // get the binary name for your used compression type - string decompProg; - if(CurrentCompressionExtension == "uncompressed") - decompProg = "copy"; - else - decompProg = _config->Find(string("Acquire::CompressionTypes::").append(CurrentCompressionExtension),""); - if(decompProg.empty() == true) - { - _error->Error("Unsupported extension: %s", CurrentCompressionExtension.c_str()); - return; - } - - // queue uri for the next stage - Stage = STAGE_DECOMPRESS_AND_VERIFY; - DestFile += ".decomp"; - Desc.URI = decompProg + ":" + FileName; - QueueURI(Desc); - SetActiveSubprocess(decompProg); -} - /*}}}*/ -// pkgAcqIndex::StageDecompressDone - Final verification /*{{{*/ -void pkgAcqIndex::StageDecompressDone(string Message, - HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cfg) -{ - 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* 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; - - // ensure the toplevel is in error state too - for (std::vector::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::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()); + bool foundStart = false; + for (std::vector::iterator cur = available_patches.begin(); + cur != available_patches.end(); ++cur) + { + if (LocalHashes != cur->result_hashes) + continue; + + available_patches.erase(available_patches.begin(), cur); + foundStart = true; + break; } - // 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()); + if (foundStart == false || unlikely(available_patches.empty() == true)) + { + if (Debug) + std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": " + << "Couldn't find the start of the patch series." << std::endl; + return false; + } - // set the TransactionManager - if(_config->FindB("Debug::Acquire::Transaction", false) == true) - std::clog << "New pkgAcqMetaSig with TransactionManager " - << TransactionManager << std::endl; + // patching with too many files is rather slow compared to a fast download + unsigned long const fileLimit = _config->FindI("Acquire::PDiffs::FileLimit", 0); + if (fileLimit != 0 && fileLimit < available_patches.size()) + { + if (Debug) + std::clog << "Need " << available_patches.size() << " diffs (Limit is " << fileLimit + << ") so fallback to complete download" << std::endl; + return false; + } - // Create the item - Desc.Description = URIDesc; - Desc.Owner = this; - Desc.ShortDesc = ShortDesc; - Desc.URI = URI; + // calculate the size of all patches we have to get + // note that all sizes are uncompressed, while we download compressed files + unsigned long long patchesSize = 0; + for (std::vector::const_iterator cur = available_patches.begin(); + cur != available_patches.end(); ++cur) + patchesSize += cur->patch_size; + unsigned long long const sizeLimit = ServerSize * _config->FindI("Acquire::PDiffs::SizeLimit", 100); + if (sizeLimit > 0 && (sizeLimit/100) < patchesSize) + { + if (Debug) + std::clog << "Need " << patchesSize << " bytes (Limit is " << sizeLimit/100 + << ") so fallback to complete download" << std::endl; + return false; + } - // 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())) + // we have something, queue the diffs + string::size_type const last_space = Description.rfind(" "); + if(last_space != string::npos) + Description.erase(last_space, Description.size()-last_space); + + /* decide if we should download patches one by one or in one go: + The first is good if the server merges patches, but many don't so client + based merging can be attempt in which case the second is better. + "bad things" will happen if patches are merged on the server, + but client side merging is attempt as well */ + bool pdiff_merge = _config->FindB("Acquire::PDiffs::Merge", true); + if (pdiff_merge == true) { - Complete = true; - Status = StatDone; - PartialFile = DestFile = GetFinalFilename(); - MetaIndexFileSignature = DestFile; - MetaIndex->QueueForSignatureVerify(this, MetaIndex->DestFile, DestFile); + // reprepro adds this flag if it has merged patches on the server + std::string const precedence = Tags.FindS("X-Patch-Precedence"); + pdiff_merge = (precedence != "merged"); } + + if (pdiff_merge == false) + new pkgAcqIndexDiffs(Owner, TransactionManager, Target, available_patches); else - QueueURI(Desc); -} - /*}}}*/ -pkgAcqMetaSig::~pkgAcqMetaSig() /*{{{*/ -{ + { + std::vector *diffs = new std::vector(available_patches.size()); + for(size_t i = 0; i < available_patches.size(); ++i) + (*diffs)[i] = new pkgAcqIndexMergeDiffs(Owner, TransactionManager, + Target, + available_patches[i], + diffs); + } + + Complete = false; + Status = StatDone; + Dequeue(); + return true; } /*}}}*/ -// pkgAcqMetaSig::GetFinalFilename - Return the full final file path /*{{{*/ -std::string pkgAcqMetaSig::GetFinalFilename() const +void pkgAcqDiffIndex::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf)/*{{{*/ { - return GetFinalFileNameFromURI(RealURI); + Item::Failed(Message,Cnf); + Status = StatDone; + + if(Debug) + std::clog << "pkgAcqDiffIndex failed: " << Desc.URI << " with " << Message << std::endl + << "Falling back to normal index file acquire" << std::endl; + + new pkgAcqIndex(Owner, TransactionManager, Target); } /*}}}*/ -// 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) +void pkgAcqDiffIndex::Done(string const &Message,HashStringList const &Hashes, /*{{{*/ + pkgAcquire::MethodConfig const * const Cnf) { - if (MetaIndexFileSignature.empty() == false) - { - DestFile = MetaIndexFileSignature; - MetaIndexFileSignature.clear(); - } - Item::Done(Message, Size, Hashes, Cfg); + if(Debug) + std::clog << "pkgAcqDiffIndex::Done(): " << Desc.URI << std::endl; - if(MetaIndex->AuthPass == false) + Item::Done(Message, Hashes, Cnf); + + string const FinalFile = GetFinalFilename(); + if(StringToBool(LookupTag(Message,"IMS-Hit"),false)) + DestFile = FinalFile; + + if(ParseDiffIndex(DestFile) == 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); - } + Failed("Message: Couldn't parse pdiff index", Cnf); + // queue for final move - this should happen even if we fail + // while parsing (e.g. on sizelimit) and download the complete file. + TransactionManager->TransactionStageCopy(this, DestFile, FinalFile); return; } - else if(MetaIndex->CheckAuthDone(Message) == true) - { - if (TransactionManager->IMSHit == false) - { - TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename()); - TransactionManager->TransactionStageCopy(MetaIndex, MetaIndex->DestFile, MetaIndex->GetFinalFilename()); - } - } + + TransactionManager->TransactionStageCopy(this, DestFile, FinalFile); + + Complete = true; + Status = StatDone; + Dequeue(); + + return; } /*}}}*/ -void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)/*{{{*/ + +// AcqIndexDiffs::AcqIndexDiffs - Constructor /*{{{*/ +// --------------------------------------------------------------------- +/* The package diff is added to the queue. one object is constructed + * for each diff and the index + */ +pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire * const Owner, + pkgAcqMetaBase * const TransactionManager, + IndexTarget const * const Target, + vector const &diffs) + : pkgAcqBaseIndex(Owner, TransactionManager, Target), + available_patches(diffs) { - Item::Failed(Message,Cnf); + DestFile = GetPartialFileNameFromURI(Target->URI); - // check if we need to fail at this point - if (MetaIndex->AuthPass == true && MetaIndex->CheckStopAuthentication(this, Message)) - return; + Debug = _config->FindB("Debug::pkgAcquire::Diffs",false); - string const FinalRelease = MetaIndex->GetFinalFilename(); - string const FinalReleasegpg = GetFinalFilename(); - string const FinalInRelease = TransactionManager->GetFinalFilename(); + Desc.Owner = this; + Description = Target->Description; + Desc.ShortDesc = Target->ShortDesc; - if (RealFileExists(FinalReleasegpg) || RealFileExists(FinalInRelease)) + if(available_patches.empty() == true) { - 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; - } + // we are done (yeah!), check hashes against the final file + DestFile = GetFinalFileNameFromURI(Target->URI); + Finish(true); } 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)) + // patching needs to be bootstrapped with the 'old' version + std::string const PartialFile = GetPartialFileNameFromURI(Target->URI); + if (RealFileExists(PartialFile) == false) { - // open the last Release if we have it - if (TransactionManager->IMSHit == false) + if (symlink(GetFinalFilename().c_str(), PartialFile.c_str()) != 0) { - 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(); + Failed("Link creation of " + PartialFile + " to " + GetFinalFilename() + " failed", NULL); + return; } } - // 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()); + // get the next diff + State = StateFetchDiff; + QueueNextDiff(); } +} + /*}}}*/ +void pkgAcqIndexDiffs::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf)/*{{{*/ +{ + Item::Failed(Message,Cnf); + Status = StatDone; - // FIXME: this is used often (e.g. in pkgAcqIndexTrans) so refactor - if (Cnf->LocalOnly == true || - StringToBool(LookupTag(Message,"Transient-Failure"),false) == false) + 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); + RenameOnError(PDiffError); + new pkgAcqIndex(Owner, TransactionManager, Target); + Finish(); +} + /*}}}*/ +// Finish - helper that cleans the item out of the fetcher queue /*{{{*/ +void pkgAcqIndexDiffs::Finish(bool allDone) +{ + if(Debug) + std::clog << "pkgAcqIndexDiffs::Finish(): " + << allDone << " " + << Desc.URI << std::endl; + + // we restore the original name, this is required, otherwise + // the file will be cleaned + if(allDone) { - // Ignore this + TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename()); + + // this is for the "real" finish + Complete = true; Status = StatDone; + Dequeue(); + if(Debug) + std::clog << "\n\nallDone: " << DestFile << "\n" << std::endl; + return; } + + if(Debug) + std::clog << "Finishing: " << Desc.URI << std::endl; + Complete = false; + Status = StatDone; + Dequeue(); + return; } /*}}}*/ -pkgAcqMetaIndex::pkgAcqMetaIndex(pkgAcquire *Owner, /*{{{*/ - pkgAcqMetaBase *TransactionManager, - string URI,string URIDesc,string ShortDesc, - string MetaIndexSigURI,string MetaIndexSigURIDesc, string MetaIndexSigShortDesc, - const vector* IndexTargets, - indexRecords* MetaIndexParser) : - pkgAcqMetaBase(Owner, IndexTargets, MetaIndexParser, URI, HashStringList(), - TransactionManager), - URIDesc(URIDesc), ShortDesc(ShortDesc), - MetaIndexSigURI(MetaIndexSigURI), MetaIndexSigURIDesc(MetaIndexSigURIDesc), - MetaIndexSigShortDesc(MetaIndexSigShortDesc) +bool pkgAcqIndexDiffs::QueueNextDiff() /*{{{*/ { - if(TransactionManager == NULL) + // calc sha1 of the just patched file + std::string const FinalFile = GetPartialFileNameFromURI(Target->URI); + + if(!FileExists(FinalFile)) { - this->TransactionManager = this; - this->TransactionManager->Add(this); + Failed("Message: No FinalFile " + FinalFile + " available", NULL); + return false; } - 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; + FileFd fd(FinalFile, FileFd::ReadOnly); + Hashes LocalHashesCalc; + LocalHashesCalc.AddFD(fd); + HashStringList const LocalHashes = LocalHashesCalc.GetHashStringList(); - // 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(Debug) + std::clog << "QueueNextDiff: " << FinalFile << " (" << LocalHashes.find(NULL)->toStr() << ")" << std::endl; - if(CheckDownloadDone(this, Message, Hashes)) + HashStringList const TargetFileHashes = GetExpectedHashesFor(Target->MetaKey); + if (unlikely(LocalHashes.usable() == false || TargetFileHashes.usable() == false)) { - // 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); + Failed("Local/Expected hashes are not usable", NULL); + return false; } -} - /*}}}*/ -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) + + // final file reached before all patches are applied + if(LocalHashes == TargetFileHashes) { - // 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(); - } + Finish(true); + return true; } - if (!MetaIndexParser->Load(DestFile)) + // remove all patches until the next matching patch is found + // this requires the Index file to be ordered + for(vector::iterator I = available_patches.begin(); + available_patches.empty() == false && + I != available_patches.end() && + I->result_hashes != LocalHashes; + ++I) { - Status = StatAuthError; - ErrorText = MetaIndexParser->ErrorText; - return false; + available_patches.erase(I); } - if (!VerifyVendor(Message)) + // error checking and falling back if no patch was found + if(available_patches.empty() == true) { - Status = StatAuthError; + Failed("No patches left to reach target", NULL); return false; } - if (_config->FindB("Debug::pkgAcquire::Auth", false)) - std::cerr << "Signature verification succeeded: " - << DestFile << std::endl; + // queue the right diff + Desc.URI = Target->URI + ".diff/" + available_patches[0].file + ".gz"; + Desc.Description = Description + " " + available_patches[0].file + string(".pdiff"); + DestFile = GetPartialFileNameFromURI(Target->URI + ".diff/" + available_patches[0].file); - // Download further indexes with verification - QueueIndexes(true); + if(Debug) + std::clog << "pkgAcqIndexDiffs::QueueNextDiff(): " << Desc.URI << std::endl; + + QueueURI(Desc); return true; } /*}}}*/ -// pkgAcqMetaBase::Custom600Headers - Get header for AcqMetaBase /*{{{*/ -// --------------------------------------------------------------------- -#if APT_PKG_ABI >= 413 -string pkgAcqMetaBase::Custom600Headers() const -#else -string pkgAcqMetaBase::Custom600Headers() -#endif +void pkgAcqIndexDiffs::Done(string const &Message, HashStringList const &Hashes, /*{{{*/ + pkgAcquire::MethodConfig const * const Cnf) { - 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(); + if(Debug) + std::clog << "pkgAcqIndexDiffs::Done(): " << Desc.URI << std::endl; - struct stat Buf; - if (stat(FinalFile.c_str(),&Buf) == 0) - Header += "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime); + Item::Done(Message, Hashes, Cnf); - 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) + // FIXME: verify this download too before feeding it to rred + std::string const FinalFile = GetPartialFileNameFromURI(Target->URI); - string const FileName = LookupTag(Message,"Filename"); - if (FileName.empty() == true) + // success in downloading a diff, enter ApplyDiff state + if(State == StateFetchDiff) { - I->Status = StatError; - I->ErrorText = "Method gave a blank filename"; - return false; - } + FileFd fd(DestFile, FileFd::ReadOnly, FileFd::Gzip); + class Hashes LocalHashesCalc; + LocalHashesCalc.AddFD(fd); + HashStringList const LocalHashes = LocalHashesCalc.GetHashStringList(); - if (FileName != I->DestFile) - { - I->Local = true; - I->Desc.URI = "copy:" + FileName; - I->QueueURI(I->Desc); - return false; - } + 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; + } - // 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()) + // rred excepts the patch as $FinalFile.ed + Rename(DestFile,FinalFile+".ed"); + + if(Debug) + std::clog << "Sending to rred method: " << FinalFile << std::endl; + + State = StateApplyDiff; + Local = true; + Desc.URI = "rred:" + FinalFile; + QueueURI(Desc); + SetActiveSubprocess("rred"); + return; + } + + + // success in download/apply a diff, queue next (if needed) + if(State == StateApplyDiff) { - // detect IMS-Hits servers haven't detected by Hash comparison - std::string const FinalFile = I->GetFinalFilename(); - if (RealFileExists(FinalFile) && Hashes.VerifyFile(FinalFile) == true) + // remove the just applied patch + available_patches.erase(available_patches.begin()); + unlink((FinalFile + ".ed").c_str()); + + // move into place + if(Debug) { - IMSHit = true; - unlink(I->DestFile.c_str()); + std::clog << "Moving patched file in place: " << std::endl + << DestFile << " -> " << FinalFile << std::endl; } - } + Rename(DestFile,FinalFile); + chmod(FinalFile.c_str(),0644); - 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(); + // see if there is more to download + if(available_patches.empty() == false) { + new pkgAcqIndexDiffs(Owner, TransactionManager, Target, + available_patches); + return Finish(); + } else + // update + DestFile = FinalFile; + return Finish(true); } +} + /*}}}*/ + +// AcqIndexMergeDiffs::AcqIndexMergeDiffs - Constructor /*{{{*/ +pkgAcqIndexMergeDiffs::pkgAcqIndexMergeDiffs(pkgAcquire * const Owner, + pkgAcqMetaBase * const TransactionManager, + IndexTarget const * const Target, + DiffInfo const &patch, + std::vector const * const allPatches) + : pkgAcqBaseIndex(Owner, TransactionManager, Target), + patch(patch), allPatches(allPatches), State(StateFetchDiff) +{ + Debug = _config->FindB("Debug::pkgAcquire::Diffs",false); + + Desc.Owner = this; + Description = Target->Description; + Desc.ShortDesc = Target->ShortDesc; + + Desc.URI = Target->URI + ".diff/" + patch.file + ".gz"; + Desc.Description = Description + " " + patch.file + string(".pdiff"); + + DestFile = GetPartialFileNameFromURI(Target->URI + ".diff/" + patch.file); + + if(Debug) + std::clog << "pkgAcqIndexMergeDiffs: " << Desc.URI << std::endl; + + QueueURI(Desc); +} + /*}}}*/ +void pkgAcqIndexMergeDiffs::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf)/*{{{*/ +{ + if(Debug) + std::clog << "pkgAcqIndexMergeDiffs failed: " << Desc.URI << " with " << Message << std::endl; - // set Item to complete as the remaining work is all local (verify etc) - I->Complete = true; + Item::Failed(Message,Cnf); + Status = StatDone; - return true; + // check if we are the first to fail, otherwise we are done here + State = StateDoneDiff; + for (std::vector::const_iterator I = allPatches->begin(); + I != allPatches->end(); ++I) + if ((*I)->State == StateErrorDiff) + return; + + // first failure means we should fallback + State = StateErrorDiff; + if (Debug) + std::clog << "Falling back to normal index file acquire" << std::endl; + DestFile = GetPartialFileNameFromURI(Target->URI); + RenameOnError(PDiffError); + new pkgAcqIndex(Owner, TransactionManager, Target); } /*}}}*/ -void pkgAcqMetaBase::QueueIndexes(bool verify) /*{{{*/ +void pkgAcqIndexMergeDiffs::Done(string const &Message, HashStringList const &Hashes, /*{{{*/ + pkgAcquire::MethodConfig const * const Cnf) { - // at this point the real Items are loaded in the fetcher - ExpectedAdditionalItems = 0; + if(Debug) + std::clog << "pkgAcqIndexMergeDiffs::Done(): " << Desc.URI << std::endl; - vector ::const_iterator Target; - for (Target = IndexTargets->begin(); - Target != IndexTargets->end(); - ++Target) - { - HashStringList ExpectedIndexHashes; - const indexRecords::checkSum *Record = MetaIndexParser->Lookup((*Target)->MetaKey); + Item::Done(Message, Hashes, Cnf); - // optional target that we do not have in the Release file are - // skipped - if (verify == true && Record == NULL && (*Target)->IsOptional()) - continue; + // FIXME: verify download before feeding it to rred + 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(); - // targets without a hash record are a error when verify is required - if (verify == true && Record == NULL) + if (fd.Size() != patch.patch_size || patch.patch_hashes != LocalHashes) { - 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; + // patchfiles are dated, so bad indicates a bad download, so kill it + unlink(DestFile.c_str()); + Failed("Patch has Size/Hashsum mismatch", NULL); + 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) ? "" : Record->MetaKeyFilename) << std::endl; + // rred expects the patch as $FinalFile.ed.$patchname.gz + Rename(DestFile, FinalFile + ".ed." + patch.file + ".gz"); + + // check if this is the last completed diff + State = StateDoneDiff; + for (std::vector::const_iterator I = allPatches->begin(); + I != allPatches->end(); ++I) + if ((*I)->State != StateDoneDiff) + { + if(Debug) + std::clog << "Not the last done diff in the batch: " << Desc.URI << std::endl; + return; + } + + // this is the last completed diff, so we are ready to apply now + State = StateApplyDiff; + // patching needs to be bootstrapped with the 'old' version + if (symlink(GetFinalFilename().c_str(), FinalFile.c_str()) != 0) + { + Failed("Link creation of " + FinalFile + " to " + GetFinalFilename() + " failed", NULL); + return; } - if (verify == true && ExpectedIndexHashes.empty() == true) + + if(Debug) + std::clog << "Sending to rred method: " << FinalFile << std::endl; + + Local = true; + Desc.URI = "rred:" + FinalFile; + QueueURI(Desc); + SetActiveSubprocess("rred"); + return; + } + // success in download/apply all diffs, clean up + else if (State == StateApplyDiff) + { + // move the result into place + std::string const Final = GetFinalFilename(); + if(Debug) + std::clog << "Queue patched file in place: " << std::endl + << DestFile << " -> " << Final << std::endl; + + // queue for copy by the transaction manager + TransactionManager->TransactionStageCopy(this, DestFile, Final); + + // ensure the ed's are gone regardless of list-cleanup + for (std::vector::const_iterator I = allPatches->begin(); + I != allPatches->end(); ++I) { - Status = StatAuthError; - strprintf(ErrorText, _("Unable to find hash sum for '%s' in Release file"), (*Target)->MetaKey.c_str()); - return; + std::string const PartialFile = GetPartialFileNameFromURI(Target->URI); + std::string patch = PartialFile + ".ed." + (*I)->patch.file + ".gz"; + unlink(patch.c_str()); } + unlink(FinalFile.c_str()); - /* 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); + // all set and done + Complete = true; + if(Debug) + std::clog << "allDone: " << DestFile << "\n" << std::endl; } } /*}}}*/ -bool pkgAcqMetaBase::VerifyVendor(string Message) /*{{{*/ + +// AcqIndex::AcqIndex - Constructor /*{{{*/ +pkgAcqIndex::pkgAcqIndex(pkgAcquire * const Owner, + pkgAcqMetaBase * const TransactionManager, + IndexTarget const * const Target) + : pkgAcqBaseIndex(Owner, TransactionManager, Target) { - string::size_type pos; + // autoselect the compression method + AutoSelectCompression(); + Init(Target->URI, Target->Description, Target->ShortDesc); - // 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) + if(_config->FindB("Debug::Acquire::Transaction", false) == true) + std::clog << "New pkgIndex with TransactionManager " + << TransactionManager << std::endl; +} + /*}}}*/ +// AcqIndex::AutoSelectCompression - Select compression /*{{{*/ +void pkgAcqIndex::AutoSelectCompression() +{ + std::vector types = APT::Configuration::getCompressionTypes(); + CompressionExtensions = ""; + if (TransactionManager->MetaIndexParser != NULL && TransactionManager->MetaIndexParser->Exists(Target->MetaKey)) { - string::size_type start = pos+strlen("NO_PUBKEY "); - string Fingerprint = Message.substr(start, Message.find("\n")-start); - missingkeys += (Fingerprint); + for (std::vector::const_iterator t = types.begin(); + t != types.end(); ++t) + { + std::string CompressedMetaKey = string(Target->MetaKey).append(".").append(*t); + if (*t == "uncompressed" || + TransactionManager->MetaIndexParser->Exists(CompressedMetaKey) == true) + CompressionExtensions.append(*t).append(" "); + } } - if(!missingkeys.empty()) - _error->Warning("%s", (msg + missingkeys).c_str()); - - string Transformed = MetaIndexParser->GetExpectedDist(); - - if (Transformed == "../project/experimental") + else { - Transformed = "experimental"; + for (std::vector::const_iterator t = types.begin(); t != types.end(); ++t) + CompressionExtensions.append(*t).append(" "); } + if (CompressionExtensions.empty() == false) + CompressionExtensions.erase(CompressionExtensions.end()-1); +} + /*}}}*/ +// AcqIndex::Init - defered Constructor /*{{{*/ +void pkgAcqIndex::Init(string const &URI, string const &URIDesc, + string const &ShortDesc) +{ + Stage = STAGE_DOWNLOAD; - pos = Transformed.rfind('/'); - if (pos != string::npos) - { - Transformed = Transformed.substr(0, pos); - } + DestFile = GetPartialFileNameFromURI(URI); - if (Transformed == ".") + size_t const nextExt = CompressionExtensions.find(' '); + if (nextExt == std::string::npos) { - Transformed = ""; + CurrentCompressionExtension = CompressionExtensions; + CompressionExtensions.clear(); } - - 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()); - } + else + { + CurrentCompressionExtension = CompressionExtensions.substr(0, nextExt); + CompressionExtensions = CompressionExtensions.substr(nextExt+1); } - /* 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()) + if (CurrentCompressionExtension == "uncompressed") { - TransactionManager->IMSHit = true; - unlink(DestFile.c_str()); - PartialFile = DestFile = GetFinalFilename(); - delete MetaIndexParser; - MetaIndexParser = LastMetaIndexParser; - LastMetaIndexParser = NULL; + Desc.URI = URI; } - - if (_config->FindB("Debug::pkgAcquire::Auth", false)) + else if (unlikely(CurrentCompressionExtension.empty())) + return; + else { - std::cerr << "Got Codename: " << MetaIndexParser->GetDist() << std::endl; - std::cerr << "Expecting Dist: " << MetaIndexParser->GetExpectedDist() << std::endl; - std::cerr << "Transformed Dist: " << Transformed << std::endl; + Desc.URI = URI + '.' + CurrentCompressionExtension; + DestFile = DestFile + '.' + CurrentCompressionExtension; } - if (MetaIndexParser->CheckDist(Transformed) == false) + if(TransactionManager->MetaIndexParser != NULL) + InitByHashIfNeeded(); + + Desc.Description = URIDesc; + Desc.Owner = this; + Desc.ShortDesc = ShortDesc; + + QueueURI(Desc); +} + /*}}}*/ +// AcqIndex::AdjustForByHash - modify URI for by-hash support /*{{{*/ +void pkgAcqIndex::InitByHashIfNeeded() +{ + // TODO: + // - (maybe?) add support for by-hash into the sources.list as flag + // - make apt-ftparchive generate the hashes (and expire?) + 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 || + TransactionManager->MetaIndexParser->GetSupportsAcquireByHash()) { - // This might become fatal one day -// Status = StatAuthError; -// ErrorText = "Conflicting distribution; expected " -// + MetaIndexParser->GetExpectedDist() + " but got " -// + MetaIndexParser->GetDist(); -// return false; - if (!Transformed.empty()) + HashStringList const Hashes = GetExpectedHashes(); + if(Hashes.usable()) { - _error->Warning(_("Conflicting distribution: %s (expected %s but got %s)"), - Desc.Description.c_str(), - Transformed.c_str(), - MetaIndexParser->GetDist().c_str()); + // FIXME: should we really use the best hash here? or a fixed one? + 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, + ByHash); + } else { + _error->Warning( + "Fetching ByHash requested but can not find record for %s", + GetMetaKey().c_str()); } } - - return true; } /*}}}*/ -// pkgAcqMetaIndex::Failed - no Release file present /*{{{*/ -void pkgAcqMetaIndex::Failed(string Message, - pkgAcquire::MethodConfig * Cnf) +// AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/ +// --------------------------------------------------------------------- +/* The only header we use is the last-modified header. */ +string pkgAcqIndex::Custom600Headers() const { - 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()); + string Final = GetFinalFilename(); - // 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()); + string msg = "\nIndex-File: true"; + struct stat Buf; + if (stat(Final.c_str(),&Buf) == 0) + msg += "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime); - // queue without any kind of hashsum support - QueueIndexes(false); - } + if(Target->IsOptional()) + msg += "\nFail-Ignore: true"; + + return msg; } /*}}}*/ -void pkgAcqMetaIndex::Finished() /*{{{*/ +// AcqIndex::Failed - getting the indexfile failed /*{{{*/ +void pkgAcqIndex::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf) { - if(_config->FindB("Debug::Acquire::Transaction", false) == true) - std::clog << "Finished: " << DestFile <TransactionHasError() == false) - TransactionManager->CommitTransaction(); + Item::Failed(Message,Cnf); + + // authorisation matches will not be fixed by other compression types + if (Status != StatAuthError) + { + if (CompressionExtensions.empty() == false) + { + Init(Target->URI, Desc.Description, Desc.ShortDesc); + Status = StatIdle; + return; + } + } + + if(Target->IsOptional() && GetExpectedHashes().empty() && Stage == STAGE_DOWNLOAD) + Status = StatDone; + else + TransactionManager->AbortTransaction(); } /*}}}*/ -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* 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) +// AcqIndex::ReverifyAfterIMS - Reverify index after an ims-hit /*{{{*/ +void pkgAcqIndex::ReverifyAfterIMS() { - // index targets + (worst case:) Release/Release.gpg - ExpectedAdditionalItems = IndexTargets->size() + 2; + // update destfile to *not* include the compression extension when doing + // a reverify (as its uncompressed on disk already) + DestFile = GetCompressedFileName(Target->URI, GetPartialFileNameFromURI(Target->URI), CurrentCompressionExtension); + + // copy FinalFile into partial/ so that we check the hash again + string FinalFile = GetFinalFilename(); + Stage = STAGE_DECOMPRESS_AND_VERIFY; + Desc.URI = "copy:" + FinalFile; + QueueURI(Desc); } /*}}}*/ -pkgAcqMetaClearSig::~pkgAcqMetaClearSig() /*{{{*/ +// 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; } /*}}}*/ -// pkgAcqMetaClearSig::Custom600Headers - Insert custom request headers /*{{{*/ -#if APT_PKG_ABI >= 413 -string pkgAcqMetaClearSig::Custom600Headers() const -#else -string pkgAcqMetaClearSig::Custom600Headers() -#endif +// AcqIndex::Done - Finished a fetch /*{{{*/ +// --------------------------------------------------------------------- +/* This goes through a number of states.. On the initial fetch the + method could possibly return an alternate filename which points + 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 const &Message, + HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cfg) { - string Header = pkgAcqMetaBase::Custom600Headers(); - Header += "\nFail-Ignore: true"; - return Header; + Item::Done(Message,Hashes,Cfg); + + switch(Stage) + { + case STAGE_DOWNLOAD: + StageDownloadDone(Message, Hashes, Cfg); + break; + case STAGE_DECOMPRESS_AND_VERIFY: + StageDecompressDone(Message, Hashes, Cfg); + break; + } } /*}}}*/ -// pkgAcqMetaClearSig::Done - We got a file /*{{{*/ -class APT_HIDDEN DummyItem : public pkgAcquire::Item +// AcqIndex::StageDownloadDone - Queue for decompress and verify /*{{{*/ +void pkgAcqIndex::StageDownloadDone(string const &Message, HashStringList const &, + pkgAcquire::MethodConfig const * const) { - std::string URI; - public: - virtual std::string DescURI() {return URI;}; + Complete = true; - DummyItem(pkgAcquire *Owner, std::string const &URI) : pkgAcquire::Item(Owner), URI(URI) + // Handle the unzipd case + string FileName = LookupTag(Message,"Alt-Filename"); + if (FileName.empty() == false) { - Status = StatDone; - DestFile = GetFinalFileNameFromURI(URI); + Stage = STAGE_DECOMPRESS_AND_VERIFY; + Local = true; + DestFile += ".decomp"; + Desc.URI = "copy:" + FileName; + QueueURI(Desc); + SetActiveSubprocess("copy"); + return; } -}; -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)) + FileName = LookupTag(Message,"Filename"); + if (FileName.empty() == true) { - pkgAcquire::Item::Failed(Message, Cnf); - RenameOnError(NotClearsigned); - TransactionManager->AbortTransaction(); - return; + Status = StatError; + ErrorText = "Method gave a blank filename"; } - if(AuthPass == false) + // 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) + Local = true; + else + EraseFileName = FileName; + + // we need to verify the file against the current Release file again + // on if-modfied-since hit to avoid a stale attack against us + if(StringToBool(LookupTag(Message,"IMS-Hit"),false) == true) { - if(CheckDownloadDone(this, Message, Hashes) == true) - QueueForSignatureVerify(this, DestFile, DestFile); + // The files timestamp matches, reverify by copy into partial/ + EraseFileName = ""; + ReverifyAfterIMS(); return; } - else if(CheckAuthDone(Message) == true) + + // If we have compressed indexes enabled, queue for hash verification + if (_config->FindB("Acquire::GzipIndexes",false)) { - 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); - } + DestFile = GetPartialFileNameFromURI(Target->URI + '.' + CurrentCompressionExtension); + EraseFileName = ""; + Stage = STAGE_DECOMPRESS_AND_VERIFY; + Desc.URI = "copy:" + FileName; + QueueURI(Desc); + SetActiveSubprocess("copy"); + return; + } + + // get the binary name for your used compression type + string decompProg; + if(CurrentCompressionExtension == "uncompressed") + decompProg = "copy"; + else + decompProg = _config->Find(string("Acquire::CompressionTypes::").append(CurrentCompressionExtension),""); + if(decompProg.empty() == true) + { + _error->Error("Unsupported extension: %s", CurrentCompressionExtension.c_str()); + return; } + + // queue uri for the next stage + Stage = STAGE_DECOMPRESS_AND_VERIFY; + DestFile += ".decomp"; + Desc.URI = decompProg + ":" + FileName; + QueueURI(Desc); + SetActiveSubprocess(decompProg); } /*}}}*/ -void pkgAcqMetaClearSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /*{{{*/ +// AcqIndex::StageDecompressDone - Final verification /*{{{*/ +void pkgAcqIndex::StageDecompressDone(string const &Message, + HashStringList const &, + pkgAcquire::MethodConfig const * const Cfg) { - Item::Failed(Message, Cnf); - - // we failed, we will not get additional items from this method - ExpectedAdditionalItems = 0; - - if (AuthPass == false) + if(!ValidateFile(DestFile)) { - // 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); + RenameOnError(InvalidFormat); + Failed(Message, Cfg); + return; } - 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; + // Done, queue for rename on transaction finished + TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename()); - /* 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); - } - } + return; } /*}}}*/ + + // 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), LocalSource(false), Version(Version), Sources(Sources), Recs(Recs), + StoreFilename(StoreFilename), Vf(Version.FileList()), Trusted(false) { Retries = _config->FindI("Acquire::Retries",0); @@ -2573,15 +2577,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->Flags & pkgCache::Flag::NotSource) != 0) 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->Flags & pkgCache::Flag::LocalSource) == pkgCache::Flag::LocalSource; + // only try to get a trusted package from another source if that source // is also trusted if(Trusted && !Index->IsTrusted()) @@ -2681,25 +2687,10 @@ 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"); @@ -2726,23 +2717,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(); @@ -2770,21 +2755,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) @@ -2792,17 +2768,26 @@ void pkgAcqArchive::Finished() StoreFilename = string(); } /*}}}*/ +std::string pkgAcqArchive::DescURI() const /*{{{*/ +{ + return Desc.URI; +} + /*}}}*/ +std::string pkgAcqArchive::ShortDesc() const /*{{{*/ +{ + return Desc.ShortDesc; +} + /*}}}*/ + // 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), IsIndexFile(IsIndexFile), ExpectedHashes(Hashes) { Retries = _config->FindI("Acquire::Retries",0); - + if(!DestFilename.empty()) DestFile = DestFilename; else if(!DestDir.empty()) @@ -2817,7 +2802,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; @@ -2834,21 +2819,11 @@ 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); + Item::Done(Message,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) { @@ -2858,11 +2833,11 @@ void pkgAcqFile::Done(string Message,unsigned long long Size,HashStringList cons } 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) { @@ -2874,7 +2849,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) @@ -2882,7 +2857,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) { @@ -2894,14 +2869,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); @@ -2918,14 +2893,7 @@ 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"; diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index 07c86f31b..97d5ea1dd 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -6,15 +6,15 @@ 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 @@ -49,7 +49,48 @@ class pkgSourceList; class IndexTarget; class pkgAcqMetaBase; -/** \brief Represents the process by which a pkgAcquire object should {{{ +class APT_HIDDEN IndexTarget /*{{{*/ +/** \brief Information about an index file. */ +{ + public: + /** \brief A URI from which the index file can be downloaded. */ + std::string const URI; + + /** \brief A description of the index file. */ + std::string const Description; + + /** \brief A shorter description of the index file. */ + std::string const ShortDesc; + + /** \brief The key by which this index file should be + * looked up within the meta signature file. + */ + std::string const MetaKey; + + virtual bool IsOptional() const { + return false; + } + + IndexTarget(std::string const &MetaKey, std::string const &ShortDesc, + std::string const &LongDesc, std::string const &URI) : + URI(URI), Description(LongDesc), ShortDesc(ShortDesc), MetaKey(MetaKey) {} +}; + /*}}}*/ +class APT_HIDDEN OptionalIndexTarget : public IndexTarget /*{{{*/ +/** \brief Information about an optional index file. */ +{ + public: + virtual bool IsOptional() const { + return true; + } + + OptionalIndexTarget(std::string const &MetaKey, std::string const &ShortDesc, + std::string const &LongDesc, std::string const &URI) : + IndexTarget(MetaKey, ShortDesc, LongDesc, URI) {} +}; + /*}}}*/ +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 +102,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 +127,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 +155,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 +175,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 +188,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 +197,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 +216,7 @@ 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 when the object was * fetched successfully. @@ -234,25 +231,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 +258,55 @@ 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; /** \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 +315,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); + Item(pkgAcquire * const Owner); /** \brief Remove this item from its owner's queue by invoking * pkgAcquire::Remove. @@ -337,6 +324,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 +346,99 @@ 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 *d; + + friend class pkgAcqMetaBase; +}; + /*}}}*/ +class APT_HIDDEN pkgAcqTransactionItem: public pkgAcquire::Item /*{{{*/ +/** \brief baseclass for the indexes files to manage them all together */ +{ + protected: + IndexTarget const * const Target; + HashStringList GetExpectedHashesFor(std::string const MetaKey) const; + + bool QueueURI(pkgAcquire::ItemDesc &Item); + + public: + /** \brief storge name until a transaction is finished */ + std::string PartialFile; + + /** \brief TransactionManager */ + pkgAcqMetaBase * 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; + virtual std::string DescURI() const { return Target->URI; } + virtual HashStringList GetExpectedHashes() const; + virtual std::string GetMetaKey() const; + virtual bool HashesRequired() const; - /** \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; - /** The hashes of the diff */ - HashStringList result_hashes; - - /** The hashes of the file after the diff is applied */ - HashStringList patch_hashes; + pkgAcqTransactionItem(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, IndexTarget const * const Target); + virtual ~pkgAcqTransactionItem(); - /** The size of the file after the diff is applied */ - unsigned long long result_size; - - /** The size of the diff itself */ - unsigned long long patch_size; + friend class pkgAcqMetaBase; }; /*}}}*/ -class pkgAcqMetaBase : public pkgAcquire::Item /*{{{*/ +class APT_HIDDEN pkgAcqMetaBase : public pkgAcqTransactionItem /*{{{*/ +/** \brief the manager of a transaction */ { void *d; protected: - std::vector Transaction; + std::vector Transaction; + IndexTarget const DataTarget; + public: /** \brief A package-system-specific parser for the meta-index file. */ indexRecords *MetaIndexParser; indexRecords *LastMetaIndexParser; + protected: /** \brief The index files which should be looked up in the meta-index * and then downloaded. */ - const std::vector* IndexTargets; + const std::vector* 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 +447,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 +458,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 /** \brief Called when authentication succeeded. * @@ -450,7 +474,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,7 +484,7 @@ 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); @@ -468,33 +492,32 @@ class pkgAcqMetaBase : public pkgAcquire::Item /*{{{*/ // 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 HashStringList GetExpectedHashes() const; + virtual bool HashesRequired() const; // 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; - pkgAcqMetaBase(pkgAcquire *Owner, - const std::vector* IndexTargets, - indexRecords* MetaIndexParser, - std::string const &RealURI, - HashStringList const &ExpectedHashes=HashStringList(), - pkgAcqMetaBase *TransactionManager=NULL); + pkgAcqMetaBase(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, + std::vector const * const IndexTargets, + IndexTarget const &DataTarget, + indexRecords* const MetaIndexParser); }; /*}}}*/ /** \brief An item that is responsible for downloading the meta-index {{{ @@ -512,36 +535,24 @@ class APT_HIDDEN pkgAcqMetaIndex : public pkgAcqMetaBase void *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; // 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); + virtual void Done(std::string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cnf); virtual void Finished(); /** \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* IndexTargets, - indexRecords* MetaIndexParser); + pkgAcqMetaIndex(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, + IndexTarget const &DataTarget, IndexTarget const &DetachedSigTarget, + const std::vector* const IndexTargets, indexRecords * const MetaIndexParser); friend class pkgAcqMetaSig; }; @@ -554,7 +565,7 @@ class APT_HIDDEN pkgAcqMetaIndex : public pkgAcqMetaBase * * \sa pkgAcqMetaIndex */ -class APT_HIDDEN pkgAcqMetaSig : public pkgAcquire::Item +class APT_HIDDEN pkgAcqMetaSig : public pkgAcqTransactionItem { void *d; @@ -565,29 +576,20 @@ 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; public: - virtual std::string DescURI() {return RealURI;}; + virtual bool HashesRequired() const { 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); + virtual void Done(std::string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cnf); /** \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, pkgAcqMetaBase * const TransactionManager, IndexTarget const * const Target, + pkgAcqMetaIndex * const MetaIndex); virtual ~pkgAcqMetaSig(); }; /*}}}*/ @@ -596,78 +598,37 @@ 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; - - /** \brief The URI of the detached meta-signature file if the clearsigned one failed. */ - std::string MetaSigURI; - - /** \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; + IndexTarget const ClearsignedTarget; + IndexTarget const DetachedDataTarget; + IndexTarget const DetachedSigTarget; public: - virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); -#if APT_PKG_ABI >= 413 + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); 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 Done(std::string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cnf); /** \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* IndexTargets, - indexRecords* MetaIndexParser); + pkgAcqMetaClearSig(pkgAcquire * const Owner, + IndexTarget const &ClearsignedTarget, + IndexTarget const &DetachedDataTarget, + IndexTarget const &DetachedSigTarget, + std::vector const * const IndexTargets, + indexRecords * 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); - + public: /** \brief Get the full pathname of the final file for the current URI */ virtual std::string GetFinalFilename() const; - pkgAcqBaseIndex(pkgAcquire *Owner, - pkgAcqMetaBase *TransactionManager, - struct IndexTarget const * const Target, - HashStringList const &ExpectedHashes, - indexRecords *MetaIndexParser); + pkgAcqBaseIndex(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, + IndexTarget const * const Target); }; /*}}}*/ /** \brief An item that is responsible for fetching an index file of {{{ @@ -705,15 +666,12 @@ class APT_HIDDEN pkgAcqDiffIndex : public pkgAcqBaseIndex virtual bool TransactionState(TransactionStates const state); 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 void Failed(std::string const &Message, pkgAcquire::MethodConfig const * const Cnf); + virtual void Done(std::string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cnf); + virtual std::string DescURI() const {return Target->URI + "Index";}; virtual std::string Custom600Headers() const; -#else - virtual std::string Custom600Headers(); -#endif + virtual std::string GetMetaKey() const; /** \brief Parse the Index file for a set of Packages diffs. * @@ -725,7 +683,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 +694,30 @@ 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, pkgAcqMetaBase * const TransactionManager, + IndexTarget const * const Target); private: APT_HIDDEN void QueueOnIMSHit() const; }; /*}}}*/ +struct APT_HIDDEN DiffInfo { /*{{{*/ + /** The filename of the diff. */ + std::string file; + + /** 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; + + /** The size of the diff itself */ + unsigned long long patch_size; +}; + /*}}}*/ /** \brief An item that is responsible for fetching client-merge patches {{{ * that need to be applied to a given package index file. * @@ -801,10 +771,12 @@ 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); + virtual void Done(std::string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cnf); + virtual std::string DescURI() const {return Target->URI + "Index";}; + virtual HashStringList GetExpectedHashes() const; + virtual bool HashesRequired() const; /** \brief Create an index merge-diff item. * @@ -817,22 +789,15 @@ 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, pkgAcqMetaBase * const TransactionManager, + IndexTarget const * const Target, + DiffInfo const &patch, std::vector const * const allPatches); }; /*}}}*/ @@ -875,7 +840,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 +870,25 @@ 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); - 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); + virtual std::string DescURI() const {return Target->URI + "IndexDiffs";}; + virtual HashStringList GetExpectedHashes() const; + virtual bool HashesRequired() const; /** \brief Create an index diff item. * @@ -940,20 +904,13 @@ 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 diffs=std::vector()); + pkgAcqIndexDiffs(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, + IndexTarget const * const Target, + std::vector const &diffs=std::vector()); }; /*}}}*/ /** \brief An acquire item that is responsible for fetching an index {{{ @@ -981,16 +938,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 +963,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(); @@ -1015,7 +972,7 @@ class APT_HIDDEN pkgAcqIndex : public pkgAcqBaseIndex void ReverifyAfterIMS(); /** \brief Validate the downloaded index file */ - bool ValidateFile(const std::string &FileName); + bool ValidateFile(std::string const &FileName); /** \brief Get the full pathname of the final file for the current URI */ virtual std::string GetFinalFilename() const; @@ -1024,82 +981,20 @@ class APT_HIDDEN pkgAcqIndex : public pkgAcqBaseIndex 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 void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); + virtual void Done(std::string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cnf); virtual std::string Custom600Headers() const; -#else - virtual std::string Custom600Headers(); -#endif - virtual std::string DescURI() {return Desc.URI;}; + virtual std::string DescURI() const {return Desc.URI;}; + virtual std::string GetMetaKey() const; + + pkgAcqIndex(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, + IndexTarget const * const Target); - /** \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; - - /** \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 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; - } -}; - /*}}}*/ /** \brief An item that is responsible for fetching a package file. {{{ * * If the package file already exists in the cache, nothing will be @@ -1109,6 +1004,9 @@ class pkgAcqArchive : public pkgAcquire::Item { void *d; + bool LocalSource; + HashStringList ExpectedHashes; + protected: /** \brief The package version being fetched. */ pkgCache::VerIterator Version; @@ -1141,7 +1039,7 @@ 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(); @@ -1151,17 +1049,15 @@ class pkgAcqArchive : public pkgAcquire::Item 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 Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); + virtual void Done(std::string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cnf); + virtual std::string DescURI() const; + virtual std::string ShortDesc() const; virtual void Finished(); -#if APT_PKG_ABI >= 413 virtual bool IsTrusted() const; -#else - virtual bool IsTrusted(); -#endif + virtual HashStringList GetExpectedHashes() const; + virtual bool HashesRequired() const; /** \brief Create a new pkgAcqArchive. * @@ -1181,8 +1077,8 @@ 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); }; /*}}}*/ @@ -1200,22 +1096,21 @@ class pkgAcqFile : public pkgAcquire::Item * Acquire::Retries. */ unsigned int Retries; - + /** \brief Should this file be considered a index file */ bool IsIndexFile; + HashStringList const ExpectedHashes; public: - + virtual HashStringList GetExpectedHashes() const; + virtual bool HashesRequired() const; + // 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 void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); + virtual void Done(std::string const &Message, HashStringList const &CalcHashes, + pkgAcquire::MethodConfig const * const Cnf); + virtual std::string DescURI() const {return Desc.URI;}; virtual std::string Custom600Headers() const; -#else - virtual std::string Custom600Headers(); -#endif /** \brief Create a new pkgAcqFile object. * @@ -1248,10 +1143,10 @@ 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); }; /*}}}*/ /** @} */ diff --git a/apt-pkg/acquire-method.cc b/apt-pkg/acquire-method.cc index c29ef469e..b77096efd 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 diff --git a/apt-pkg/acquire-worker.cc b/apt-pkg/acquire-worker.cc index 9254e20a3..099a1f87d 100644 --- a/apt-pkg/acquire-worker.cc +++ b/apt-pkg/acquire-worker.cc @@ -55,8 +55,8 @@ pkgAcquire::Worker::Worker(Queue *Q,MethodConfig *Cnf, CurrentItem = 0; TotalSize = 0; CurrentSize = 0; - - Construct(); + + Construct(); } /*}}}*/ // Worker::Worker - Constructor for method config startup /*{{{*/ @@ -70,8 +70,8 @@ pkgAcquire::Worker::Worker(MethodConfig *Cnf) CurrentItem = 0; TotalSize = 0; CurrentSize = 0; - - Construct(); + + Construct(); } /*}}}*/ // Worker::Construct - Constructor helper /*{{{*/ @@ -136,7 +136,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 +145,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 +165,7 @@ bool pkgAcquire::Worker::Start() close(Pipes[2]); OutReady = false; InReady = true; - + // Read the configuration data if (WaitFd(InFd) == false || ReadMessages() == false) @@ -174,7 +174,7 @@ bool pkgAcquire::Worker::Start() RunMessages(); if (OwnerQ != 0) SendConfiguration(); - + return true; } /*}}}*/ @@ -201,7 +201,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); @@ -215,15 +215,15 @@ bool pkgAcquire::Worker::RunMessages() // update used mirror string UsedMirror = LookupTag(Message,"UsedMirror", ""); - if (!UsedMirror.empty() && + if (!UsedMirror.empty() && Itm && - Itm->Description.find(" ") != string::npos) + Itm->Description.find(" ") != string::npos) { Itm->Description.replace(0, Itm->Description.find(" "), UsedMirror); // FIXME: will we need this as well? //Itm->ShortDesc = UsedMirror; } - + // Determine the message number and dispatch switch (Number) { @@ -232,18 +232,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,7 +252,7 @@ bool pkgAcquire::Worker::RunMessages() _error->Error("Method gave invalid 103 Redirect message"); break; } - + string NewURI = LookupTag(Message,"New-URI",URI.c_str()); Itm->URI = NewURI; @@ -272,7 +272,7 @@ bool pkgAcquire::Worker::RunMessages() Log->Done(Desc); break; } - + // 200 URI Start case 200: { @@ -281,23 +281,23 @@ 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)); + Itm->Owner->Start(Message, TotalSize); // Display update before completion if (Log != 0 && Log->MorePulses == true) Log->Pulse(Itm->Owner->GetOwner()); - + if (Log != 0) Log->Fetch(*Itm); break; } - + // 201 URI Done case 201: { @@ -306,7 +306,7 @@ bool pkgAcquire::Worker::RunMessages() _error->Error("Method gave invalid 201 URI Done message"); break; } - + pkgAcquire::Item *Owner = Itm->Owner; pkgAcquire::ItemDesc Desc = *Itm; @@ -316,22 +316,11 @@ bool pkgAcquire::Worker::RunMessages() // 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 + + HashStringList const ExpectedHashes = Owner->GetExpectedHashes(); + // see if we got hashes to verify HashStringList ReceivedHashes; for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type) { @@ -340,6 +329,18 @@ bool pkgAcquire::Worker::RunMessages() if (hashsum.empty() == false) ReceivedHashes.push_back(HashString(*type, hashsum)); } + // not all methods always sent Hashes our way + if (ExpectedHashes.usable() == true && ReceivedHashes.usable() == false) + { + std::string const filename = LookupTag(Message, "Filename", Owner->DestFile.c_str()); + if (filename.empty() == false && 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) { @@ -348,30 +349,66 @@ bool pkgAcquire::Worker::RunMessages() 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) + 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(); - // Log that we are done - if (Log != 0) + // decide if what we got is what we expected + bool consideredOkay = false; + bool const isIMSHit = StringToBool(LookupTag(Message,"IMS-Hit"),false) || + StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false); + if (ExpectedHashes.usable()) { - if (isHit) + if (ReceivedHashes.usable() == false) { - /* Hide 'hits' for local only sources - we also manage to - hide gets */ - if (Config->LocalOnly == false) - Log->IMSHit(Desc); - } + /* 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 - Log->Done(Desc); + consideredOkay = false; + + } + else if (Owner->HashesRequired() == true) + consideredOkay = false; + else + consideredOkay = true; + + if (consideredOkay == true) + { + Owner->Done(Message, ReceivedHashes, Config); + ItemDone(); + + // Log that we are done + if (Log != 0) + { + if (isIMSHit) + { + /* Hide 'hits' for local only sources - we also manage to + hide gets */ + if (Config->LocalOnly == false) + Log->IMSHit(Desc); + } + else + Log->Done(Desc); + } + } + else + { + Owner->Status = pkgAcquire::Item::StatAuthError; + Owner->Failed(Message,Config); + ItemDone(); + + if (Log != 0) + Log->Fail(Desc); } break; - } - + } + // 400 URI Failure case 400: { @@ -408,18 +445,18 @@ bool pkgAcquire::Worker::RunMessages() Log->Fail(Desc); 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 +469,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 +484,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,10 +500,10 @@ 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' " @@ -536,12 +573,12 @@ 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->Owner->GetExpectedHashes(); for (HashStringList::const_iterator hs = hsl.begin(); hs != hsl.end(); ++hs) Message += "\nExpected-" + hs->HashType() + ": " + hs->HashValue(); if(Item->Owner->FileSize > 0) @@ -564,7 +601,7 @@ bool pkgAcquire::Worker::QueueItem(pkgAcquire::Queue::QItem *Item) clog << " -> " << Access << ':' << QuoteString(Message,"\n") << endl; OutQueue += Message; OutReady = true; - + return true; } /*}}}*/ @@ -586,7 +623,7 @@ bool pkgAcquire::Worker::OutFdReady() OutQueue.erase(0,Res); if (OutQueue.empty() == true) OutReady = false; - + return true; } /*}}}*/ @@ -608,7 +645,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 +657,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 /*{{{*/ diff --git a/apt-pkg/contrib/hashes.cc b/apt-pkg/contrib/hashes.cc index 0fa443b4a..11a7e479b 100644 --- a/apt-pkg/contrib/hashes.cc +++ b/apt-pkg/contrib/hashes.cc @@ -23,6 +23,7 @@ #include #include #include +#include #include #include /*}}}*/ @@ -178,6 +179,15 @@ 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::supported(char const * const type) /*{{{*/ { for (char const * const * t = HashString::SupportedHashes(); *t != NULL; ++t) diff --git a/apt-pkg/contrib/hashes.h b/apt-pkg/contrib/hashes.h index ac13c8ace..176ce4faa 100644 --- a/apt-pkg/contrib/hashes.h +++ b/apt-pkg/contrib/hashes.h @@ -87,6 +87,15 @@ 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; + /** check if the given hash type is supported * * @param type to check diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index d672b4fd8..185248619 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -742,13 +742,13 @@ bool debDebPkgFileIndex::Merge(pkgCacheGenerator& Gen, OpProgress* Prog) const // and give it to the list parser debDebFileParser Parser(DebControl, DebFile); - if(Gen.SelectFile(DebFile, "local", *this) == false) + if(Gen.SelectFile(DebFile, "local", *this, pkgCache::Flag::LocalSource) == 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()); diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index aa2db8149..eb5e78e3b 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -192,11 +192,13 @@ vector * debReleaseIndex::ComputeIndexTargets() const { vector const SectionEntries = src->second; for (vector::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); + char const * const ShortDesc = "Sources"; + IndexTarget * const Target = new IndexTarget( + SourceIndexURISuffix(ShortDesc, (*I)->Section), + ShortDesc, + Info(ShortDesc, (*I)->Section), + SourceIndexURI(ShortDesc, (*I)->Section) + ); IndexTargets->push_back (Target); } } @@ -212,11 +214,13 @@ vector * debReleaseIndex::ComputeIndexTargets() const { continue; for (vector ::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); + char const * const ShortDesc = "Packages"; + IndexTarget * const Target = new IndexTarget( + IndexURISuffix(ShortDesc, (*I)->Section, a->first), + ShortDesc, + Info (ShortDesc, (*I)->Section, a->first), + IndexURI(ShortDesc, (*I)->Section, a->first) + ); IndexTargets->push_back (Target); sections.insert((*I)->Section); } @@ -235,11 +239,13 @@ vector * debReleaseIndex::ComputeIndexTargets() const { s != sections.end(); ++s) { for (std::vector::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); + std::string const ShortDesc = "Translation-" + *l; + IndexTarget * const Target = new OptionalIndexTarget( + TranslationIndexURISuffix(l->c_str(), *s), + ShortDesc, + Info (ShortDesc.c_str(), *s), + TranslationIndexURI(l->c_str(), *s) + ); IndexTargets->push_back(Target); } } @@ -249,8 +255,6 @@ vector * debReleaseIndex::ComputeIndexTargets() const { /*}}}*/ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const { - bool const tryInRelease = _config->FindB("Acquire::TryInRelease", true); - indexRecords * const iR = new indexRecords(Dist); if (Trusted == ALWAYS_TRUSTED) iR->SetTrusted(true); @@ -258,37 +262,17 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const iR->SetTrusted(false); // special case for --print-uris - if (GetAll) { - vector *targets = ComputeIndexTargets(); - for (vector ::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); + vector const * const targets = ComputeIndexTargets(); +#define APT_TARGET(X) IndexTarget("", X, MetaIndexInfo(X), MetaIndexURI(X)) + pkgAcqMetaBase * const TransactionManager = new pkgAcqMetaClearSig(Owner, + APT_TARGET("InRelease"), APT_TARGET("Release"), APT_TARGET("Release.gpg"), + targets, iR); +#undef APT_TARGET + if (GetAll) + { + for (vector ::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; } diff --git a/apt-pkg/indexrecords.cc b/apt-pkg/indexrecords.cc index de2617833..c26868cac 100644 --- a/apt-pkg/indexrecords.cc +++ b/apt-pkg/indexrecords.cc @@ -73,7 +73,7 @@ APT_PURE indexRecords::checkSum *indexRecords::Lookup(const string MetaKey) APT_PURE bool indexRecords::Exists(string const &MetaKey) const { - return Entries.count(MetaKey) == 1; + return Entries.find(MetaKey) != Entries.end(); } bool indexRecords::Load(const string Filename) /*{{{*/ diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h index 2ba23c5c0..b4d56611a 100644 --- a/apt-pkg/pkgcache.h +++ b/apt-pkg/pkgcache.h @@ -190,7 +190,12 @@ 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 */ + NotAutomatic=(1<<1), /*!< archive has a default pin of 1 */ + ButAutomaticUpgrades=(1<<2), /*!< (together with the previous) archive has a default pin of 100 */ + LocalSource=(1<<3), /*!< local sources can't and will not be verified by hashes */ + }; }; protected: -- cgit v1.2.3 From 3679515479136179e0d95325a6559fcc6d0af7f8 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 6 Jun 2015 19:16:45 +0200 Subject: check patch hashes in rred worker instead of in the handler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rred is responsible for unpacking and reading the patch files in one go, but we currently only have hashes for the uncompressed patch files, so the handler read the entire patch file before dispatching it to the worker which would read it again – both with an implicit uncompress. Worse, while the workers operate in parallel the handler is the central orchestration unit, so having it busy with work means the workers do (potentially) nothing. This means rred is working with 'untrusted' data, which is bad. Yet, having the unpack in the handler meant that the untrusted uncompress was done as root which isn't better either. Now, we have it at least contained in a binary which we can harden a bit better. In the long run, we want hashes for the compressed patch files through to be safe. --- apt-pkg/acquire-item.cc | 95 ++++++++++++++++++++++++++++------------------- apt-pkg/acquire-item.h | 2 + apt-pkg/acquire-method.cc | 14 +++---- apt-pkg/acquire-method.h | 5 ++- 4 files changed, 67 insertions(+), 49 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index ec6ec6e84..7b69ee993 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -95,6 +95,19 @@ static std::string GetCompressedFileName(std::string const &URI, std::string con return Name; } /*}}}*/ +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(indexRecords const * const MetaIndexParser, pkgAcqMetaBase * const TransactionManager, pkgAcquire::Item * const I) /*{{{*/ { if(MetaIndexParser->IsAlwaysTrusted() || _config->FindB("Acquire::AllowInsecureRepositories") == true) @@ -1860,6 +1873,9 @@ void pkgAcqIndexDiffs::Failed(string const &Message,pkgAcquire::MethodConfig con << "Falling back to normal index file acquire" << std::endl; DestFile = GetPartialFileNameFromURI(Target->URI); RenameOnError(PDiffError); + 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(); } @@ -1968,28 +1984,13 @@ void pkgAcqIndexDiffs::Done(string const &Message, HashStringList const &Hashes, Item::Done(Message, Hashes, Cnf); - // FIXME: verify this download too before feeding it to rred 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; @@ -2000,18 +2001,17 @@ void pkgAcqIndexDiffs::Done(string const &Message, HashStringList const &Hashes, 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; @@ -2031,6 +2031,18 @@ void pkgAcqIndexDiffs::Done(string const &Message, HashStringList const &Hashes, } } /*}}}*/ +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(); +} + /*}}}*/ // AcqIndexMergeDiffs::AcqIndexMergeDiffs - Constructor /*{{{*/ pkgAcqIndexMergeDiffs::pkgAcqIndexMergeDiffs(pkgAcquire * const Owner, @@ -2079,6 +2091,9 @@ void pkgAcqIndexMergeDiffs::Failed(string const &Message,pkgAcquire::MethodConfi std::clog << "Falling back to normal index file acquire" << std::endl; DestFile = GetPartialFileNameFromURI(Target->URI); RenameOnError(PDiffError); + 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); } /*}}}*/ @@ -2090,26 +2105,10 @@ void pkgAcqIndexMergeDiffs::Done(string const &Message, HashStringList const &Ha Item::Done(Message, Hashes, Cnf); - // FIXME: verify download before feeding it to rred 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; @@ -2158,7 +2157,7 @@ void pkgAcqIndexMergeDiffs::Done(string const &Message, HashStringList const &Ha I != allPatches->end(); ++I) { std::string const PartialFile = GetPartialFileNameFromURI(Target->URI); - std::string patch = PartialFile + ".ed." + (*I)->patch.file + ".gz"; + std::string const patch = GetMergeDiffsPatchFileName(PartialFile, (*I)->patch.file); unlink(patch.c_str()); } unlink(FinalFile.c_str()); @@ -2170,6 +2169,24 @@ void pkgAcqIndexMergeDiffs::Done(string const &Message, HashStringList const &Ha } } /*}}}*/ +std::string pkgAcqIndexMergeDiffs::Custom600Headers() const /*{{{*/ +{ + if(State != StateApplyDiff) + return pkgAcqBaseIndex::Custom600Headers(); + std::ostringstream patchhashes; + unsigned int seen_patches = 0; + for (std::vector::const_iterator I = allPatches->begin(); + I != allPatches->end(); ++I) + { + 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; + } + patchhashes << pkgAcqBaseIndex::Custom600Headers(); + return patchhashes.str(); +} + /*}}}*/ // AcqIndex::AcqIndex - Constructor /*{{{*/ pkgAcqIndex::pkgAcqIndex(pkgAcquire * const Owner, diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index 97d5ea1dd..f24af1aec 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -774,6 +774,7 @@ class APT_HIDDEN pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); virtual void Done(std::string const &Message, HashStringList const &Hashes, pkgAcquire::MethodConfig const * const Cnf); + virtual std::string Custom600Headers() const; virtual std::string DescURI() const {return Target->URI + "Index";}; virtual HashStringList GetExpectedHashes() const; virtual bool HashesRequired() const; @@ -886,6 +887,7 @@ class APT_HIDDEN pkgAcqIndexDiffs : public pkgAcqBaseIndex virtual void Done(std::string const &Message, HashStringList const &Hashes, pkgAcquire::MethodConfig const * const Cnf); + virtual std::string Custom600Headers() const; virtual std::string DescURI() const {return Target->URI + "IndexDiffs";}; virtual HashStringList GetExpectedHashes() const; virtual bool HashesRequired() const; diff --git a/apt-pkg/acquire-method.cc b/apt-pkg/acquire-method.cc index b77096efd..a8fc75f8e 100644 --- a/apt-pkg/acquire-method.cc +++ b/apt-pkg/acquire-method.cc @@ -388,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(); @@ -403,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 { diff --git a/apt-pkg/acquire-method.h b/apt-pkg/acquire-method.h index 399454892..6480eb4b5 100644 --- a/apt-pkg/acquire-method.h +++ b/apt-pkg/acquire-method.h @@ -76,11 +76,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);}; -- cgit v1.2.3 From 4f51fd8636592a96aecf17c8bf4cfdb3ea2207cc Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 8 Jun 2015 00:06:41 +0200 Subject: support hashes for compressed pdiff files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At the moment we only have hashes for the uncompressed pdiff files, but via the new '$HASH-Download' field in the .diff/Index hashes can be provided for the .gz compressed pdiff file, which apt will pick up now and use to verify the download. Now, we "just" need a buy in from the creators of repositories… --- apt-pkg/acquire-item.cc | 72 +++++++++++++++++++++++++++++++++++++++-------- apt-pkg/acquire-item.h | 11 +++----- apt-pkg/contrib/hashes.cc | 11 ++++++-- apt-pkg/contrib/hashes.h | 7 +++++ apt-pkg/indexrecords.cc | 4 +-- 5 files changed, 80 insertions(+), 25 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 7b69ee993..a3f47242f 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -152,14 +152,18 @@ HashStringList pkgAcqMetaBase::GetExpectedHashes() const APT_CONST bool pkgAcqIndexDiffs::HashesRequired() const { - /* FIXME: We have only hashes for uncompressed pdiffs. - rred uncompresses them on the fly while parsing. - In StateFetchDiff state we also uncompress on the fly for hash check. - Hashes are checked while searching for (next) patch to apply. */ + /* 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(); } @@ -168,11 +172,15 @@ 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 == StateApplyDiff) + if (State == StateFetchDiff) + return patch.download_hashes; + else if (State == StateApplyDiff) return GetExpectedHashesFor(Target->MetaKey); return HashStringList(); } @@ -1618,7 +1626,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string const &IndexDiffFile) /*{{{*/ std::vector::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; @@ -1630,8 +1638,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string const &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 @@ -1679,10 +1686,9 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string const &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()) @@ -1694,6 +1700,48 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string const &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::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::iterator cur = available_patches.begin(); cur != available_patches.end(); ++cur) @@ -1729,7 +1777,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string const &IndexDiffFile) /*{{{*/ unsigned long long patchesSize = 0; for (std::vector::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) { diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index f24af1aec..910e4131b 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -705,17 +705,14 @@ struct APT_HIDDEN DiffInfo { /*{{{*/ /** The filename of the diff. */ std::string file; - /** The hashes of the diff */ + /** The hashes of the file after the diff is applied */ HashStringList result_hashes; - /** The hashes of the file after the diff is applied */ + /** The hashes of the diff */ HashStringList patch_hashes; - /** The size of the file after the diff is applied */ - unsigned long long result_size; - - /** The size of the diff itself */ - unsigned long long patch_size; + /** The hashes of the compressed diff */ + HashStringList download_hashes; }; /*}}}*/ /** \brief An item that is responsible for fetching client-merge patches {{{ diff --git a/apt-pkg/contrib/hashes.cc b/apt-pkg/contrib/hashes.cc index 11a7e479b..46cf0ba08 100644 --- a/apt-pkg/contrib/hashes.cc +++ b/apt-pkg/contrib/hashes.cc @@ -188,6 +188,13 @@ unsigned long long HashStringList::FileSize() const /*{{{*/ 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) @@ -361,9 +368,7 @@ 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 diff --git a/apt-pkg/contrib/hashes.h b/apt-pkg/contrib/hashes.h index 176ce4faa..e8d84da9e 100644 --- a/apt-pkg/contrib/hashes.h +++ b/apt-pkg/contrib/hashes.h @@ -96,6 +96,13 @@ class HashStringList */ 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 diff --git a/apt-pkg/indexrecords.cc b/apt-pkg/indexrecords.cc index c26868cac..7e6da9558 100644 --- a/apt-pkg/indexrecords.cc +++ b/apt-pkg/indexrecords.cc @@ -121,9 +121,7 @@ bool indexRecords::Load(const string Filename) /*{{{*/ 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)); + Sum->Hashes.FileSize(Size); APT_IGNORE_DEPRECATED(Sum->Hash = HashString(HashString::SupportedHashes()[i],Hash);) Entries[Name] = Sum; } -- cgit v1.2.3 From 9b8c28f430a8fbe73252cc3e87b6e88e9d5063d9 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 8 Jun 2015 11:20:01 +0200 Subject: cleanup pdiff support detection decision Its a bit unclean to create an item just to let the item decide that it can't do anything and let it fail, so instead we let the item creator decide in all cases if patching should be attempted. Also pulls a small trick to get the hashes for the current file without calculating them by looking at the 'old' Release file if we have it. Git-Dch: Ignore --- apt-pkg/acquire-item.cc | 85 ++++++++++++++++++++++++++----------------------- apt-pkg/acquire-item.h | 5 --- 2 files changed, 45 insertions(+), 45 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index a3f47242f..13e971e9f 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -925,24 +925,36 @@ void pkgAcqMetaBase::QueueIndexes(bool const verify) /*{{{*/ Target != IndexTargets->end(); ++Target) { - if (verify == true && TransactionManager->MetaIndexParser->Exists((*Target)->MetaKey) == false) + bool trypdiff = _config->FindB("Acquire::PDiffs", true); + if (verify == true) { - // optional target that we do not have in the Release file are skipped - if ((*Target)->IsOptional()) - continue; + 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; + 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; + } + + // 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)); - /* 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 || - TransactionManager->MetaIndexParser->Exists((*Target)->MetaKey + ".diff/Index") == true)) + // 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); @@ -1477,26 +1489,7 @@ pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire * const Owner, if(Debug) std::clog << "pkgAcqDiffIndex: " << Desc.URI << std::endl; - // look for the current package file - CurrentPackagesFile = GetFinalFileNameFromURI(Target->URI); - - // 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); - } /*}}}*/ // AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/ @@ -1570,6 +1563,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string const &IndexDiffFile) /*{{{*/ return false; } + std::string const CurrentPackagesFile = GetFinalFileNameFromURI(Target->URI); HashStringList const TargetFileHashes = GetExpectedHashesFor(Target->MetaKey); if (TargetFileHashes.usable() == false || ServerHashes != TargetFileHashes) { @@ -1581,7 +1575,23 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string const &IndexDiffFile) /*{{{*/ return false; } - if (ServerHashes.VerifyFile(CurrentPackagesFile) == true) + HashStringList LocalHashes; + // try avoiding calculating the hash here as this is costly + if (TransactionManager->LastMetaIndexParser != NULL) + { + indexRecords::checkSum * const R = TransactionManager->LastMetaIndexParser->Lookup(Target->MetaKey); + if (R != NULL) + LocalHashes = R->Hashes; + } + 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) @@ -1590,14 +1600,9 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string const &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 available_patches; diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index 910e4131b..e823a64d2 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -648,11 +648,6 @@ class APT_HIDDEN pkgAcqDiffIndex : public pkgAcqBaseIndex /** \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). */ -- cgit v1.2.3 From 8d041b4f4f353079268039dcbfd8b5e575196b66 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 8 Jun 2015 15:22:01 +0200 Subject: do not request files if we expect an IMS hit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we have a file on disk and the hashes are the same in the new Release file and the old one we have on disk we know that if we ask the server for the file, we will at best get an IMS hit – at worse the server doesn't support this and sends us the (unchanged) file and we have to run all our checks on it again for nothing. So, we can save ourselves (and the servers) some unneeded requests if we figure this out on our own. --- apt-pkg/acquire-item.cc | 77 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 50 insertions(+), 27 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 13e971e9f..511bbbc64 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -119,6 +119,16 @@ static bool AllowInsecureRepositories(indexRecords const * const MetaIndexParser return false; } /*}}}*/ +static HashStringList GetExpectedHashesFromFor(indexRecords * const Parser, std::string const MetaKey)/*{{{*/ +{ + if (Parser == NULL) + return HashStringList(); + indexRecords::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. @@ -372,6 +382,25 @@ bool pkgAcqDiffIndex::TransactionState(TransactionStates const state) } /*}}}*/ +class APT_HIDDEN NoActionItem : public pkgAcquire::Item /*{{{*/ +/* The sole purpose of this class is having an item which does nothing to + reach its done state to prevent cleanup deleting the mentioned file. + Handy in cases in which we know we have the file already, like IMS-Hits. */ +{ + IndexTarget const * const Target; + public: + virtual std::string DescURI() const {return Target->URI;}; + virtual HashStringList GetExpectedHashes() const {return HashStringList();}; + + NoActionItem(pkgAcquire * const Owner, IndexTarget const * 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 * const Owner) : @@ -644,12 +673,7 @@ pkgAcqTransactionItem::~pkgAcqTransactionItem() /*{{{*/ /*}}}*/ HashStringList pkgAcqTransactionItem::GetExpectedHashesFor(std::string const MetaKey) const /*{{{*/ { - if (TransactionManager->MetaIndexParser == NULL) - return HashStringList(); - indexRecords::checkSum * const R = TransactionManager->MetaIndexParser->Lookup(MetaKey); - if (R == NULL) - return HashStringList(); - return R->Hashes; + return GetExpectedHashesFromFor(TransactionManager->MetaIndexParser, MetaKey); } /*}}}*/ @@ -939,6 +963,23 @@ void pkgAcqMetaBase::QueueIndexes(bool const verify) /*{{{*/ 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 + trypdiff = false; // no file to patch + // check if we have patches available trypdiff &= TransactionManager->MetaIndexParser->Exists((*Target)->MetaKey + ".diff/Index"); } @@ -1085,20 +1126,6 @@ string pkgAcqMetaClearSig::Custom600Headers() const } /*}}}*/ // pkgAcqMetaClearSig::Done - We got a file /*{{{*/ -class APT_HIDDEN DummyItem : public pkgAcquire::Item -{ - IndexTarget const * const Target; - public: - virtual std::string DescURI() const {return Target->URI;}; - virtual HashStringList GetExpectedHashes() const {return HashStringList();}; - - DummyItem(pkgAcquire * const Owner, IndexTarget const * const Target) : - pkgAcquire::Item(Owner), Target(Target) - { - Status = StatDone; - DestFile = GetFinalFileNameFromURI(Target->URI); - } -}; void pkgAcqMetaClearSig::Done(std::string const &Message, HashStringList const &Hashes, pkgAcquire::MethodConfig const * const Cnf) @@ -1131,8 +1158,8 @@ void pkgAcqMetaClearSig::Done(std::string const &Message, // 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, &DetachedDataTarget); - new DummyItem(Owner, &DetachedSigTarget); + new NoActionItem(Owner, &DetachedDataTarget); + new NoActionItem(Owner, &DetachedSigTarget); } } } @@ -1578,11 +1605,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string const &IndexDiffFile) /*{{{*/ HashStringList LocalHashes; // try avoiding calculating the hash here as this is costly if (TransactionManager->LastMetaIndexParser != NULL) - { - indexRecords::checkSum * const R = TransactionManager->LastMetaIndexParser->Lookup(Target->MetaKey); - if (R != NULL) - LocalHashes = R->Hashes; - } + LocalHashes = GetExpectedHashesFromFor(TransactionManager->LastMetaIndexParser, Target->MetaKey); if (LocalHashes.usable() == false) { FileFd fd(CurrentPackagesFile, FileFd::ReadOnly); -- cgit v1.2.3 From 4cd86fc61960404ef7dd8a474c2dff2002016824 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 8 Jun 2015 16:08:53 +0200 Subject: remove debianism file-content verification MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The code requires every index file we download to have a Package field, but that doesn't hold true for all index we might want to download in the future. Some might not even be deb822 formatted files… The check was needed as apt used to accept unverifiable files like Translation-*, but nowadays it requires hashes for these as well. Even for unsigned repositories we interpret the Release file as binding now, which means this check isn't triggerable expect for repositories which do not have a Release file at all – something which is highly discouraged! Git-Dch: Ignore --- apt-pkg/acquire-item.cc | 39 ++------------------------------------- apt-pkg/acquire-item.h | 3 --- 2 files changed, 2 insertions(+), 40 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 511bbbc64..a1357fb15 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -2430,33 +2430,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 @@ -2557,20 +2530,12 @@ void pkgAcqIndex::StageDownloadDone(string const &Message, HashStringList const } /*}}}*/ // AcqIndex::StageDecompressDone - Final verification /*{{{*/ -void pkgAcqIndex::StageDecompressDone(string const &Message, +void pkgAcqIndex::StageDecompressDone(string const &, HashStringList const &, - pkgAcquire::MethodConfig const * const Cfg) + pkgAcquire::MethodConfig const * const) { - if(!ValidateFile(DestFile)) - { - RenameOnError(InvalidFormat); - Failed(Message, Cfg); - return; - } - // Done, queue for rename on transaction finished TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename()); - return; } /*}}}*/ diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index e823a64d2..38a7a8662 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -965,9 +965,6 @@ 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(std::string const &FileName); - /** \brief Get the full pathname of the final file for the current URI */ virtual std::string GetFinalFilename() const; -- cgit v1.2.3 From 1e0f0f28e1025f42a8172eb72f3e87984eb2b939 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 9 Jun 2015 11:59:22 +0200 Subject: configureable acquire targets to download additional files First pass at making the acquire system capable of downloading files based on configuration rather than hardcoded entries. It is now possible to instruct 'deb' and 'deb-src' sources.list lines to download more than just Packages/Translation-* and Sources files. Details on how to do that can be found in the included documentation file. --- apt-pkg/contrib/configuration.cc | 4 +- apt-pkg/contrib/configuration.h | 11 +- apt-pkg/deb/debmetaindex.cc | 317 ++++++++++++++++++--------------------- apt-pkg/deb/debmetaindex.h | 8 - apt-pkg/init.cc | 20 ++- 5 files changed, 173 insertions(+), 187 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/configuration.cc b/apt-pkg/contrib/configuration.cc index 42e35d32a..2500ab631 100644 --- a/apt-pkg/contrib/configuration.cc +++ b/apt-pkg/contrib/configuration.cc @@ -259,7 +259,7 @@ vector Configuration::FindVector(const char *Name) const return FindVector(Name, ""); } #endif -vector Configuration::FindVector(const char *Name, std::string const &Default) const +vector Configuration::FindVector(const char *Name, std::string const &Default, bool const Keys) const { vector Vec; const Item *Top = Lookup(Name); @@ -272,7 +272,7 @@ vector 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 FindVector(const char *Name, std::string const &Default = "") const; - std::vector FindVector(std::string const &Name, std::string const &Default = "") const { return FindVector(Name.c_str(), Default); }; -#else - std::vector FindVector(const char *Name, std::string const &Default) const; - std::vector FindVector(std::string const &Name, std::string const &Default) const { return FindVector(Name.c_str(), Default); }; - std::vector FindVector(const char *Name) const; - std::vector FindVector(std::string const &Name) const { return FindVector(Name.c_str(), ""); }; -#endif + std::vector FindVector(const char *Name, std::string const &Default = "", bool const Keys = false) const; + std::vector 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/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index eb5e78e3b..8fef05ab0 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -23,25 +23,6 @@ using namespace std; -string debReleaseIndex::Info(const char *Type, string const &Section, string const &Arch) const -{ - string Info = ::URI::SiteOnly(URI) + ' '; - if (Dist[Dist.size() - 1] == '/') - { - if (Dist != "/") - Info += Dist; - } - else - { - Info += Dist + '/' + Section; - if (Arch.empty() != true) - Info += " " + Arch; - } - Info += " "; - Info += Type; - return Info; -} - string debReleaseIndex::MetaIndexInfo(const char *Type) const { string Info = ::URI::SiteOnly(URI) + ' '; @@ -92,81 +73,6 @@ std::string debReleaseIndex::LocalFileName() const return ""; } -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; -} - - -string debReleaseIndex::IndexURI(const char *Type, string const &Section, string const &Arch) const -{ - if (Dist[Dist.size() - 1] == '/') - { - string Res; - if (Dist != "/") - Res = URI + Dist; - else - Res = URI; - return Res + Type; - } - else - return URI + "dists/" + Dist + '/' + IndexURISuffix(Type, Section, Arch); - } - -string debReleaseIndex::SourceIndexURISuffix(const char *Type, const string &Section) const -{ - string Res =""; - if (Dist[Dist.size() - 1] != '/') - Res += Section + "/source/"; - return Res + Type; -} - -string debReleaseIndex::SourceIndexURI(const char *Type, const string &Section) const -{ - string Res; - if (Dist[Dist.size() - 1] == '/') - { - if (Dist != "/") - Res = URI + Dist; - else - Res = URI; - return Res + Type; - } - else - return URI + "dists/" + Dist + "/" + SourceIndexURISuffix(Type, Section); -} - -string debReleaseIndex::TranslationIndexURISuffix(const char *Type, const string &Section) const -{ - string Res =""; - if (Dist[Dist.size() - 1] != '/') - Res += Section + "/i18n/Translation-"; - return Res + Type; -} - -string debReleaseIndex::TranslationIndexURI(const char *Type, const string &Section) const -{ - string Res; - if (Dist[Dist.size() - 1] == '/') - { - if (Dist != "/") - Res = URI + Dist; - else - Res = URI; - return Res + Type; - } - else - return URI + "dists/" + Dist + "/" + TranslationIndexURISuffix(Type, Section); -} - debReleaseIndex::debReleaseIndex(string const &URI, string const &Dist) : metaIndex(URI, Dist, "deb"), Trusted(CHECK_TRUST) {} @@ -184,73 +90,161 @@ debReleaseIndex::~debReleaseIndex() { delete *S; } -vector * debReleaseIndex::ComputeIndexTargets() const { - vector * IndexTargets = new vector ; +vector * debReleaseIndex::ComputeIndexTargets() const +{ + vector * IndexTargets = new vector ; - map >::const_iterator const src = ArchEntries.find("source"); - if (src != ArchEntries.end()) { - vector const SectionEntries = src->second; - for (vector::const_iterator I = SectionEntries.begin(); - I != SectionEntries.end(); ++I) { - char const * const ShortDesc = "Sources"; - IndexTarget * const Target = new IndexTarget( - SourceIndexURISuffix(ShortDesc, (*I)->Section), - ShortDesc, - Info(ShortDesc, (*I)->Section), - SourceIndexURI(ShortDesc, (*I)->Section) - ); - IndexTargets->push_back (Target); - } - } + bool const flatArchive = (Dist[Dist.length() - 1] == '/'); + std::string baseURI = URI; + if (flatArchive) + { + if (Dist != "/") + baseURI += Dist; + } + else + baseURI += "dists/" + Dist + "/"; + std::string const Release = (Dist == "/") ? "" : Dist; + std::string const Site = ::URI::SiteOnly(URI); + std::vector lang = APT::Configuration::getLanguages(true); + if (lang.empty()) + lang.push_back("none"); + map >::const_iterator const src = ArchEntries.find("source"); + if (src != ArchEntries.end()) + { + std::vector const targets = _config->FindVector("APT::Acquire::Targets::deb-src", "", true); + for (std::vector::const_iterator T = targets.begin(); T != targets.end(); ++T) + { +#define APT_T_CONFIG(X) _config->Find(std::string("APT::Acquire::Targets::deb-src::") + *T + "::" + (X)) + std::string const URI = APT_T_CONFIG(flatArchive ? "flatURI" : "URI"); + std::string const ShortDesc = APT_T_CONFIG("ShortDescription"); + std::string const LongDesc = APT_T_CONFIG(flatArchive ? "flatDescription" : "Description"); + bool const IsOptional = _config->FindB(std::string("APT::Acquire::Targets::deb-src::") + *T + "::Optional", true); +#undef APT_T_CONFIG + if (URI.empty()) + continue; - // Only source release - if (IndexTargets->empty() == false && ArchEntries.size() == 1) - return IndexTargets; + vector const SectionEntries = src->second; + for (vector::const_iterator I = SectionEntries.begin(); + I != SectionEntries.end(); ++I) + { + for (vector::const_iterator l = lang.begin(); l != lang.end(); ++l) + { + if (*l == "none" && URI.find("$(LANGUAGE)") != std::string::npos) + continue; + + struct SubstVar subst[] = { + { "$(SITE)", &Site }, + { "$(RELEASE)", &Release }, + { "$(COMPONENT)", &((*I)->Section) }, + { "$(LANGUAGE)", &(*l) }, + { NULL, NULL } + }; + std::string const name = SubstVar(URI, subst); + IndexTarget * Target; + if (IsOptional == true) + { + Target = new OptionalIndexTarget( + name, + SubstVar(ShortDesc, subst), + SubstVar(LongDesc, subst), + baseURI + name + ); + } + else + { + Target = new IndexTarget( + name, + SubstVar(ShortDesc, subst), + SubstVar(LongDesc, subst), + baseURI + name + ); + } + IndexTargets->push_back(Target); + + if (URI.find("$(LANGUAGE)") == std::string::npos) + break; + } - std::set sections; - for (map >::const_iterator a = ArchEntries.begin(); - a != ArchEntries.end(); ++a) { - if (a->first == "source") - continue; - for (vector ::const_iterator I = a->second.begin(); - I != a->second.end(); ++I) { - char const * const ShortDesc = "Packages"; - IndexTarget * const Target = new IndexTarget( - IndexURISuffix(ShortDesc, (*I)->Section, a->first), - ShortDesc, - Info (ShortDesc, (*I)->Section, a->first), - IndexURI(ShortDesc, (*I)->Section, a->first) - ); - IndexTargets->push_back (Target); - sections.insert((*I)->Section); - } - } + if (URI.find("$(COMPONENT)") == std::string::npos) + break; + } + } + } - std::vector lang = APT::Configuration::getLanguages(true); - std::vector::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::const_iterator s = sections.begin(); - s != sections.end(); ++s) { - for (std::vector::const_iterator l = lang.begin(); - l != lang.end(); ++l) { - std::string const ShortDesc = "Translation-" + *l; - IndexTarget * const Target = new OptionalIndexTarget( - TranslationIndexURISuffix(l->c_str(), *s), - ShortDesc, - Info (ShortDesc.c_str(), *s), - TranslationIndexURI(l->c_str(), *s) - ); - IndexTargets->push_back(Target); - } - } + // Only source release + if (IndexTargets->empty() == false && ArchEntries.size() == 1) + return IndexTargets; - return IndexTargets; + std::vector const targets = _config->FindVector("APT::Acquire::Targets::deb", "", true); + for (std::vector::const_iterator T = targets.begin(); T != targets.end(); ++T) + { +#define APT_T_CONFIG(X) _config->Find(std::string("APT::Acquire::Targets::deb::") + *T + "::" + (X)) + std::string const URI = APT_T_CONFIG(flatArchive ? "flatURI" : "URI"); + std::string const ShortDesc = APT_T_CONFIG("ShortDescription"); + std::string const LongDesc = APT_T_CONFIG(flatArchive ? "flatDescription" : "Description"); + bool const IsOptional = _config->FindB(std::string("APT::Acquire::Targets::deb::") + *T + "::Optional", true); +#undef APT_T_CONFIG + if (URI.empty()) + continue; + + for (map >::const_iterator a = ArchEntries.begin(); + a != ArchEntries.end(); ++a) + { + if (a->first == "source") + continue; + + for (vector ::const_iterator I = a->second.begin(); + I != a->second.end(); ++I) { + + for (vector::const_iterator l = lang.begin(); l != lang.end(); ++l) + { + if (*l == "none" && URI.find("$(LANGUAGE)") != std::string::npos) + continue; + + struct SubstVar subst[] = { + { "$(SITE)", &Site }, + { "$(RELEASE)", &Release }, + { "$(COMPONENT)", &((*I)->Section) }, + { "$(LANGUAGE)", &(*l) }, + { "$(ARCHITECTURE)", &(a->first) }, + { NULL, NULL } + }; + std::string const name = SubstVar(URI, subst); + IndexTarget * Target; + if (IsOptional == true) + { + Target = new OptionalIndexTarget( + name, + SubstVar(ShortDesc, subst), + SubstVar(LongDesc, subst), + baseURI + name + ); + } + else + { + Target = new IndexTarget( + name, + SubstVar(ShortDesc, subst), + SubstVar(LongDesc, subst), + baseURI + name + ); + } + IndexTargets->push_back(Target); + + if (URI.find("$(LANGUAGE)") == std::string::npos) + break; + } + + if (URI.find("$(COMPONENT)") == std::string::npos) + break; + } + + if (URI.find("$(ARCHITECTURE)") == std::string::npos) + break; + } + } + + return IndexTargets; } /*}}}*/ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const @@ -361,17 +355,6 @@ void debReleaseIndex::PushSectionEntry(string const &Arch, const debSectionEntry ArchEntries[Arch].push_back(Entry); } -void debReleaseIndex::PushSectionEntry(const debSectionEntry *Entry) { - if (Entry->IsSrc == true) - PushSectionEntry("source", Entry); - else { - for (map >::iterator a = ArchEntries.begin(); - a != ArchEntries.end(); ++a) { - a->second.push_back(Entry); - } - } -} - debReleaseIndex::debSectionEntry::debSectionEntry (string const &Section, bool const &IsSrc): Section(Section), IsSrc(IsSrc) {} diff --git a/apt-pkg/deb/debmetaindex.h b/apt-pkg/deb/debmetaindex.h index 94d005760..e1c1d91ef 100644 --- a/apt-pkg/deb/debmetaindex.h +++ b/apt-pkg/deb/debmetaindex.h @@ -47,7 +47,6 @@ class APT_HIDDEN debReleaseIndex : public metaIndex { virtual std::string ArchiveURI(std::string const &File) const {return URI + File;}; virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false) const; std::vector * ComputeIndexTargets() const; - std::string Info(const char *Type, std::string const &Section, std::string const &Arch="") const; std::string MetaIndexInfo(const char *Type) const; std::string MetaIndexFile(const char *Types) const; @@ -58,12 +57,6 @@ class APT_HIDDEN debReleaseIndex : public metaIndex { #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 *GetIndexFiles(); void SetTrusted(bool const Trusted); @@ -71,7 +64,6 @@ class APT_HIDDEN debReleaseIndex : public metaIndex { void PushSectionEntry(std::vector const &Archs, const debSectionEntry *Entry); void PushSectionEntry(std::string const &Arch, const debSectionEntry *Entry); - void PushSectionEntry(const debSectionEntry *Entry); }; class APT_HIDDEN debDebFileMetaIndex : public metaIndex diff --git a/apt-pkg/init.cc b/apt-pkg/init.cc index f756eab26..50ea2b49e 100644 --- a/apt-pkg/init.cc +++ b/apt-pkg/init.cc @@ -101,8 +101,26 @@ bool pkgInitConfig(Configuration &Cnf) // The default user we drop to in the methods Cnf.CndSet("APT::Sandbox::User", "_apt"); + Cnf.CndSet("APT::Acquire::Targets::deb::Packages::URI", "$(COMPONENT)/binary-$(ARCHITECTURE)/Packages"); + Cnf.CndSet("APT::Acquire::Targets::deb::Packages::flatURI", "Packages"); + Cnf.CndSet("APT::Acquire::Targets::deb::Packages::ShortDescription", "Packages"); + Cnf.CndSet("APT::Acquire::Targets::deb::Packages::Description", "$(SITE) $(RELEASE)/$(COMPONENT) $(ARCHITECTURE) Packages"); + Cnf.CndSet("APT::Acquire::Targets::deb::Packages::flatDescription", "$(SITE) $(RELEASE) Packages"); + Cnf.CndSet("APT::Acquire::Targets::deb::Packages::Optional", false); + Cnf.CndSet("APT::Acquire::Targets::deb::Translations::URI", "$(COMPONENT)/i18n/Translation-$(LANGUAGE)"); + Cnf.CndSet("APT::Acquire::Targets::deb::Translations::flatURI", "$(LANGUAGE)"); + Cnf.CndSet("APT::Acquire::Targets::deb::Translations::ShortDescription", "Translation-$(LANGUAGE)"); + Cnf.CndSet("APT::Acquire::Targets::deb::Translations::Description", "$(SITE) $(RELEASE)/$(COMPONENT) Translation-$(LANGUAGE)"); + Cnf.CndSet("APT::Acquire::Targets::deb::Translations::flatDescription", "$(SITE) $(RELEASE) Translation-$(LANGUAGE)"); + Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::URI", "$(COMPONENT)/source/Sources"); + Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::flatURI", "Sources"); + Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::ShortDescription", "Sources"); + Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::Description", "$(SITE) $(RELEASE)/$(COMPONENT) Sources"); + Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::flatDescription", "$(SITE) $(RELEASE) Sources"); + Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::Optional", false); + bool Res = true; - + // Read an alternate config file const char *Cfg = getenv("APT_CONFIG"); if (Cfg != 0 && strlen(Cfg) != 0) -- cgit v1.2.3 From 59148d9630bbbd53c6aa10da0fcdbd579797502a Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 10 Jun 2015 19:22:41 +0200 Subject: abstract the code to iterate over all targets a bit We have two places in the code which need to iterate over targets and do certain things with it. The first one is actually creating these targets for download and the second instance pepares certain targets for reading. Git-Dch: Ignore --- apt-pkg/deb/debmetaindex.cc | 197 +++++++++++++++++++++++--------------------- 1 file changed, 103 insertions(+), 94 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 8fef05ab0..c35f3b0a4 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -90,10 +90,11 @@ debReleaseIndex::~debReleaseIndex() { delete *S; } -vector * debReleaseIndex::ComputeIndexTargets() const +template +void foreachTarget(std::string const URI, std::string const Dist, + std::map > const &ArchEntries, + CallC Call) { - vector * IndexTargets = new vector ; - bool const flatArchive = (Dist[Dist.length() - 1] == '/'); std::string baseURI = URI; if (flatArchive) @@ -108,7 +109,7 @@ vector * debReleaseIndex::ComputeIndexTargets() const std::vector lang = APT::Configuration::getLanguages(true); if (lang.empty()) lang.push_back("none"); - map >::const_iterator const src = ArchEntries.find("source"); + map >::const_iterator const src = ArchEntries.find("source"); if (src != ArchEntries.end()) { std::vector const targets = _config->FindVector("APT::Acquire::Targets::deb-src", "", true); @@ -123,8 +124,8 @@ vector * debReleaseIndex::ComputeIndexTargets() const if (URI.empty()) continue; - vector const SectionEntries = src->second; - for (vector::const_iterator I = SectionEntries.begin(); + vector const SectionEntries = src->second; + for (vector::const_iterator I = SectionEntries.begin(); I != SectionEntries.end(); ++I) { for (vector::const_iterator l = lang.begin(); l != lang.end(); ++l) @@ -139,27 +140,7 @@ vector * debReleaseIndex::ComputeIndexTargets() const { "$(LANGUAGE)", &(*l) }, { NULL, NULL } }; - std::string const name = SubstVar(URI, subst); - IndexTarget * Target; - if (IsOptional == true) - { - Target = new OptionalIndexTarget( - name, - SubstVar(ShortDesc, subst), - SubstVar(LongDesc, subst), - baseURI + name - ); - } - else - { - Target = new IndexTarget( - name, - SubstVar(ShortDesc, subst), - SubstVar(LongDesc, subst), - baseURI + name - ); - } - IndexTargets->push_back(Target); + Call(baseURI, *T, URI, ShortDesc, LongDesc, IsOptional, subst); if (URI.find("$(LANGUAGE)") == std::string::npos) break; @@ -171,10 +152,6 @@ vector * debReleaseIndex::ComputeIndexTargets() const } } - // Only source release - if (IndexTargets->empty() == false && ArchEntries.size() == 1) - return IndexTargets; - std::vector const targets = _config->FindVector("APT::Acquire::Targets::deb", "", true); for (std::vector::const_iterator T = targets.begin(); T != targets.end(); ++T) { @@ -187,13 +164,13 @@ vector * debReleaseIndex::ComputeIndexTargets() const if (URI.empty()) continue; - for (map >::const_iterator a = ArchEntries.begin(); + for (map >::const_iterator a = ArchEntries.begin(); a != ArchEntries.end(); ++a) { if (a->first == "source") continue; - for (vector ::const_iterator I = a->second.begin(); + for (vector ::const_iterator I = a->second.begin(); I != a->second.end(); ++I) { for (vector::const_iterator l = lang.begin(); l != lang.end(); ++l) @@ -209,27 +186,7 @@ vector * debReleaseIndex::ComputeIndexTargets() const { "$(ARCHITECTURE)", &(a->first) }, { NULL, NULL } }; - std::string const name = SubstVar(URI, subst); - IndexTarget * Target; - if (IsOptional == true) - { - Target = new OptionalIndexTarget( - name, - SubstVar(ShortDesc, subst), - SubstVar(LongDesc, subst), - baseURI + name - ); - } - else - { - Target = new IndexTarget( - name, - SubstVar(ShortDesc, subst), - SubstVar(LongDesc, subst), - baseURI + name - ); - } - IndexTargets->push_back(Target); + Call(baseURI, *T, URI, ShortDesc, LongDesc, IsOptional, subst); if (URI.find("$(LANGUAGE)") == std::string::npos) break; @@ -243,9 +200,51 @@ vector * debReleaseIndex::ComputeIndexTargets() const break; } } +} + + +struct ComputeIndexTargetsClass +{ + vector * const IndexTargets; + + void operator()(std::string const &baseURI, std::string const &/*TargetName*/, + std::string const &URI, std::string const &ShortDesc, std::string const &LongDesc, + bool const IsOptional, struct SubstVar const * const subst) + { + std::string const name = SubstVar(URI, subst); + IndexTarget * Target; + if (IsOptional == true) + { + Target = new OptionalIndexTarget( + name, + SubstVar(ShortDesc, subst), + SubstVar(LongDesc, subst), + baseURI + name + ); + } + else + { + Target = new IndexTarget( + name, + SubstVar(ShortDesc, subst), + SubstVar(LongDesc, subst), + baseURI + name + ); + } + IndexTargets->push_back(Target); + } - return IndexTargets; + ComputeIndexTargetsClass() : IndexTargets(new vector ) {} +}; + +vector * debReleaseIndex::ComputeIndexTargets() const +{ + ComputeIndexTargetsClass comp; + foreachTarget(URI, Dist, ArchEntries, comp); + return comp.IndexTargets; } + + /*}}}*/ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const { @@ -303,45 +302,55 @@ bool debReleaseIndex::IsTrusted() const return FileExists(VerifiedSigFile); } -vector *debReleaseIndex::GetIndexFiles() { - if (Indexes != NULL) - return Indexes; - - Indexes = new vector ; - map >::const_iterator const src = ArchEntries.find("source"); - if (src != ArchEntries.end()) { - vector const SectionEntries = src->second; - for (vector::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 const lang = APT::Configuration::getLanguages(true); - map > sections; - for (map >::const_iterator a = ArchEntries.begin(); - a != ArchEntries.end(); ++a) { - if (a->first == "source") - continue; - for (vector::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 >::const_iterator s = sections.begin(); - s != sections.end(); ++s) - for (set::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; +struct GetIndexFilesClass +{ + vector * const Indexes; + std::string const URI; + std::string const Release; + bool const IsTrusted; + + void operator()(std::string const &/*baseURI*/, std::string const &TargetName, + std::string const &/*URI*/, std::string const &/*ShortDesc*/, std::string const &/*LongDesc*/, + bool const /*IsOptional*/, struct SubstVar const * const subst) + { + if (TargetName == "Packages") + { + Indexes->push_back(new debPackagesIndex( + URI, + Release, + SubstVar("$(COMPONENT)", subst), + IsTrusted, + SubstVar("$(ARCHITECTURE)", subst) + )); + } + else if (TargetName == "Sources") + Indexes->push_back(new debSourcesIndex( + URI, + Release, + SubstVar("$(COMPONENT)", subst), + IsTrusted + )); + else if (TargetName == "Translations") + Indexes->push_back(new debTranslationsIndex( + URI, + Release, + SubstVar("$(COMPONENT)", subst), + SubstVar("$(LANGUAGE)", subst) + )); + } + + GetIndexFilesClass(std::string const &URI, std::string const &Release, bool const IsTrusted) : + Indexes(new vector ), URI(URI), Release(Release), IsTrusted(IsTrusted) {} +}; + +std::vector *debReleaseIndex::GetIndexFiles() +{ + if (Indexes != NULL) + return Indexes; + + GetIndexFilesClass comp(URI, Dist, IsTrusted()); + foreachTarget(URI, Dist, ArchEntries, comp); + return Indexes = comp.Indexes; } void debReleaseIndex::PushSectionEntry(vector const &Archs, const debSectionEntry *Entry) { -- cgit v1.2.3 From d3a869e35503638e3483228fbfc95b7143568ad0 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 10 Jun 2015 21:24:47 +0200 Subject: store all targets data in IndexTarget struct We still need an API for the targets, so slowly prepare the IndexTargets to let them take this job. Git-Dch: Ignore --- apt-pkg/acquire-item.cc | 15 ++++-- apt-pkg/acquire-item.h | 31 ++++-------- apt-pkg/deb/debmetaindex.cc | 114 +++++++++++++++++++++----------------------- apt-pkg/init.cc | 12 ++--- 4 files changed, 82 insertions(+), 90 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index a1357fb15..e92ccc08b 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -382,6 +382,15 @@ bool pkgAcqDiffIndex::TransactionState(TransactionStates const state) } /*}}}*/ +// IndexTarget - Constructor /*{{{*/ +IndexTarget::IndexTarget(std::string const &MetaKey, std::string const &ShortDesc, + std::string const &LongDesc, std::string const &URI, bool const IsOptional, + std::map const &Options) : + URI(URI), Description(LongDesc), ShortDesc(ShortDesc), MetaKey(MetaKey), IsOptional(IsOptional), Options(Options) +{ +} + /*}}}*/ + class APT_HIDDEN NoActionItem : public pkgAcquire::Item /*{{{*/ /* The sole purpose of this class is having an item which does nothing to reach its done state to prevent cleanup deleting the mentioned file. @@ -955,7 +964,7 @@ void pkgAcqMetaBase::QueueIndexes(bool const verify) /*{{{*/ if (TransactionManager->MetaIndexParser->Exists((*Target)->MetaKey) == false) { // optional targets that we do not have in the Release file are skipped - if ((*Target)->IsOptional()) + if ((*Target)->IsOptional) continue; Status = StatAuthError; @@ -2388,7 +2397,7 @@ string pkgAcqIndex::Custom600Headers() const 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; @@ -2410,7 +2419,7 @@ void pkgAcqIndex::Failed(string const &Message,pkgAcquire::MethodConfig const * } } - if(Target->IsOptional() && GetExpectedHashes().empty() && Stage == STAGE_DOWNLOAD) + if(Target->IsOptional && GetExpectedHashes().empty() && Stage == STAGE_DOWNLOAD) Status = StatDone; else TransactionManager->AbortTransaction(); diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index 38a7a8662..a2571e1cd 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -28,6 +28,7 @@ #include #include +#include #ifndef APT_8_CLEANER_HEADERS #include @@ -49,7 +50,7 @@ class pkgSourceList; class IndexTarget; class pkgAcqMetaBase; -class APT_HIDDEN IndexTarget /*{{{*/ +class IndexTarget /*{{{*/ /** \brief Information about an index file. */ { public: @@ -63,30 +64,18 @@ class APT_HIDDEN IndexTarget /*{{{*/ std::string const ShortDesc; /** \brief The key by which this index file should be - * looked up within the meta signature file. - */ + looked up within the meta index file. */ std::string const MetaKey; - virtual bool IsOptional() const { - return false; - } + /** \brief Is it okay if the file isn't found in the meta index */ + bool const IsOptional; - IndexTarget(std::string const &MetaKey, std::string const &ShortDesc, - std::string const &LongDesc, std::string const &URI) : - URI(URI), Description(LongDesc), ShortDesc(ShortDesc), MetaKey(MetaKey) {} -}; - /*}}}*/ -class APT_HIDDEN OptionalIndexTarget : public IndexTarget /*{{{*/ -/** \brief Information about an optional index file. */ -{ - public: - virtual bool IsOptional() const { - return true; - } + /** \brief Target specific options defined by the implementation */ + std::map const Options; - OptionalIndexTarget(std::string const &MetaKey, std::string const &ShortDesc, - std::string const &LongDesc, std::string const &URI) : - IndexTarget(MetaKey, ShortDesc, LongDesc, URI) {} + IndexTarget(std::string const &MetaKey, std::string const &ShortDesc, + std::string const &LongDesc, std::string const &URI, bool const IsOptional, + std::map const &Options); }; /*}}}*/ class pkgAcquire::Item : public WeakPointable /*{{{*/ diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index c35f3b0a4..f038f12f5 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -116,12 +116,12 @@ void foreachTarget(std::string const URI, std::string const Dist, for (std::vector::const_iterator T = targets.begin(); T != targets.end(); ++T) { #define APT_T_CONFIG(X) _config->Find(std::string("APT::Acquire::Targets::deb-src::") + *T + "::" + (X)) - std::string const URI = APT_T_CONFIG(flatArchive ? "flatURI" : "URI"); + std::string const MetaKey = APT_T_CONFIG(flatArchive ? "flatMetaKey" : "MetaKey"); std::string const ShortDesc = APT_T_CONFIG("ShortDescription"); std::string const LongDesc = APT_T_CONFIG(flatArchive ? "flatDescription" : "Description"); bool const IsOptional = _config->FindB(std::string("APT::Acquire::Targets::deb-src::") + *T + "::Optional", true); #undef APT_T_CONFIG - if (URI.empty()) + if (MetaKey.empty()) continue; vector const SectionEntries = src->second; @@ -130,23 +130,24 @@ void foreachTarget(std::string const URI, std::string const Dist, { for (vector::const_iterator l = lang.begin(); l != lang.end(); ++l) { - if (*l == "none" && URI.find("$(LANGUAGE)") != std::string::npos) + if (*l == "none" && MetaKey.find("$(LANGUAGE)") != std::string::npos) continue; - struct SubstVar subst[] = { - { "$(SITE)", &Site }, - { "$(RELEASE)", &Release }, - { "$(COMPONENT)", &((*I)->Section) }, - { "$(LANGUAGE)", &(*l) }, - { NULL, NULL } - }; - Call(baseURI, *T, URI, ShortDesc, LongDesc, IsOptional, subst); - - if (URI.find("$(LANGUAGE)") == std::string::npos) + std::map Options; + Options.insert(std::make_pair("SITE", Site)); + Options.insert(std::make_pair("RELEASE", Release)); + Options.insert(std::make_pair("COMPONENT", (*I)->Section)); + Options.insert(std::make_pair("LANGUAGE", *l)); + Options.insert(std::make_pair("ARCHITECTURE", "source")); + Options.insert(std::make_pair("BASE_URI", baseURI)); + Options.insert(std::make_pair("CREATED_BY", *T)); + Call(MetaKey, ShortDesc, LongDesc, IsOptional, Options); + + if (MetaKey.find("$(LANGUAGE)") == std::string::npos) break; } - if (URI.find("$(COMPONENT)") == std::string::npos) + if (MetaKey.find("$(COMPONENT)") == std::string::npos) break; } } @@ -156,12 +157,12 @@ void foreachTarget(std::string const URI, std::string const Dist, for (std::vector::const_iterator T = targets.begin(); T != targets.end(); ++T) { #define APT_T_CONFIG(X) _config->Find(std::string("APT::Acquire::Targets::deb::") + *T + "::" + (X)) - std::string const URI = APT_T_CONFIG(flatArchive ? "flatURI" : "URI"); + std::string const MetaKey = APT_T_CONFIG(flatArchive ? "flatMetaKey" : "MetaKey"); std::string const ShortDesc = APT_T_CONFIG("ShortDescription"); std::string const LongDesc = APT_T_CONFIG(flatArchive ? "flatDescription" : "Description"); bool const IsOptional = _config->FindB(std::string("APT::Acquire::Targets::deb::") + *T + "::Optional", true); #undef APT_T_CONFIG - if (URI.empty()) + if (MetaKey.empty()) continue; for (map >::const_iterator a = ArchEntries.begin(); @@ -175,28 +176,28 @@ void foreachTarget(std::string const URI, std::string const Dist, for (vector::const_iterator l = lang.begin(); l != lang.end(); ++l) { - if (*l == "none" && URI.find("$(LANGUAGE)") != std::string::npos) + if (*l == "none" && MetaKey.find("$(LANGUAGE)") != std::string::npos) continue; - struct SubstVar subst[] = { - { "$(SITE)", &Site }, - { "$(RELEASE)", &Release }, - { "$(COMPONENT)", &((*I)->Section) }, - { "$(LANGUAGE)", &(*l) }, - { "$(ARCHITECTURE)", &(a->first) }, - { NULL, NULL } - }; - Call(baseURI, *T, URI, ShortDesc, LongDesc, IsOptional, subst); - - if (URI.find("$(LANGUAGE)") == std::string::npos) + std::map Options; + Options.insert(std::make_pair("SITE", Site)); + Options.insert(std::make_pair("RELEASE", Release)); + Options.insert(std::make_pair("COMPONENT", (*I)->Section)); + Options.insert(std::make_pair("LANGUAGE", *l)); + Options.insert(std::make_pair("ARCHITECTURE", a->first)); + Options.insert(std::make_pair("BASE_URI", baseURI)); + Options.insert(std::make_pair("CREATED_BY", *T)); + Call(MetaKey, ShortDesc, LongDesc, IsOptional, Options); + + if (MetaKey.find("$(LANGUAGE)") == std::string::npos) break; } - if (URI.find("$(COMPONENT)") == std::string::npos) + if (MetaKey.find("$(COMPONENT)") == std::string::npos) break; } - if (URI.find("$(ARCHITECTURE)") == std::string::npos) + if (MetaKey.find("$(ARCHITECTURE)") == std::string::npos) break; } } @@ -207,30 +208,23 @@ struct ComputeIndexTargetsClass { vector * const IndexTargets; - void operator()(std::string const &baseURI, std::string const &/*TargetName*/, - std::string const &URI, std::string const &ShortDesc, std::string const &LongDesc, - bool const IsOptional, struct SubstVar const * const subst) + void operator()(std::string MetaKey, std::string ShortDesc, std::string LongDesc, + bool const IsOptional, std::map Options) { - std::string const name = SubstVar(URI, subst); - IndexTarget * Target; - if (IsOptional == true) - { - Target = new OptionalIndexTarget( - name, - SubstVar(ShortDesc, subst), - SubstVar(LongDesc, subst), - baseURI + name - ); - } - else + for (std::map::const_iterator O = Options.begin(); O != Options.end(); ++O) { - Target = new IndexTarget( - name, - SubstVar(ShortDesc, subst), - SubstVar(LongDesc, subst), - baseURI + name - ); + 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 = new IndexTarget( + MetaKey, + ShortDesc, + LongDesc, + Options.find("BASE_URI")->second + MetaKey, + IsOptional, + Options + ); IndexTargets->push_back(Target); } @@ -256,7 +250,7 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const // special case for --print-uris vector const * const targets = ComputeIndexTargets(); -#define APT_TARGET(X) IndexTarget("", X, MetaIndexInfo(X), MetaIndexURI(X)) +#define APT_TARGET(X) IndexTarget("", X, MetaIndexInfo(X), MetaIndexURI(X), false, std::map()) pkgAcqMetaBase * const TransactionManager = new pkgAcqMetaClearSig(Owner, APT_TARGET("InRelease"), APT_TARGET("Release"), APT_TARGET("Release.gpg"), targets, iR); @@ -309,33 +303,33 @@ struct GetIndexFilesClass std::string const Release; bool const IsTrusted; - void operator()(std::string const &/*baseURI*/, std::string const &TargetName, - std::string const &/*URI*/, std::string const &/*ShortDesc*/, std::string const &/*LongDesc*/, - bool const /*IsOptional*/, struct SubstVar const * const subst) + void operator()(std::string const &/*URI*/, std::string const &/*ShortDesc*/, std::string const &/*LongDesc*/, + bool const /*IsOptional*/, std::map Options) { + std::string const TargetName = Options.find("CREATED_BY")->second; if (TargetName == "Packages") { Indexes->push_back(new debPackagesIndex( URI, Release, - SubstVar("$(COMPONENT)", subst), + Options.find("COMPONENT")->second, IsTrusted, - SubstVar("$(ARCHITECTURE)", subst) + Options.find("ARCHITECTURE")->second )); } else if (TargetName == "Sources") Indexes->push_back(new debSourcesIndex( URI, Release, - SubstVar("$(COMPONENT)", subst), + Options.find("COMPONENT")->second, IsTrusted )); else if (TargetName == "Translations") Indexes->push_back(new debTranslationsIndex( URI, Release, - SubstVar("$(COMPONENT)", subst), - SubstVar("$(LANGUAGE)", subst) + Options.find("COMPONENT")->second, + Options.find("LANGUAGE")->second )); } diff --git a/apt-pkg/init.cc b/apt-pkg/init.cc index 50ea2b49e..e2239a906 100644 --- a/apt-pkg/init.cc +++ b/apt-pkg/init.cc @@ -101,19 +101,19 @@ bool pkgInitConfig(Configuration &Cnf) // The default user we drop to in the methods Cnf.CndSet("APT::Sandbox::User", "_apt"); - Cnf.CndSet("APT::Acquire::Targets::deb::Packages::URI", "$(COMPONENT)/binary-$(ARCHITECTURE)/Packages"); - Cnf.CndSet("APT::Acquire::Targets::deb::Packages::flatURI", "Packages"); + Cnf.CndSet("APT::Acquire::Targets::deb::Packages::MetaKey", "$(COMPONENT)/binary-$(ARCHITECTURE)/Packages"); + Cnf.CndSet("APT::Acquire::Targets::deb::Packages::flatMetaKey", "Packages"); Cnf.CndSet("APT::Acquire::Targets::deb::Packages::ShortDescription", "Packages"); Cnf.CndSet("APT::Acquire::Targets::deb::Packages::Description", "$(SITE) $(RELEASE)/$(COMPONENT) $(ARCHITECTURE) Packages"); Cnf.CndSet("APT::Acquire::Targets::deb::Packages::flatDescription", "$(SITE) $(RELEASE) Packages"); Cnf.CndSet("APT::Acquire::Targets::deb::Packages::Optional", false); - Cnf.CndSet("APT::Acquire::Targets::deb::Translations::URI", "$(COMPONENT)/i18n/Translation-$(LANGUAGE)"); - Cnf.CndSet("APT::Acquire::Targets::deb::Translations::flatURI", "$(LANGUAGE)"); + Cnf.CndSet("APT::Acquire::Targets::deb::Translations::MetaKey", "$(COMPONENT)/i18n/Translation-$(LANGUAGE)"); + Cnf.CndSet("APT::Acquire::Targets::deb::Translations::flatMetaKey", "$(LANGUAGE)"); Cnf.CndSet("APT::Acquire::Targets::deb::Translations::ShortDescription", "Translation-$(LANGUAGE)"); Cnf.CndSet("APT::Acquire::Targets::deb::Translations::Description", "$(SITE) $(RELEASE)/$(COMPONENT) Translation-$(LANGUAGE)"); Cnf.CndSet("APT::Acquire::Targets::deb::Translations::flatDescription", "$(SITE) $(RELEASE) Translation-$(LANGUAGE)"); - Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::URI", "$(COMPONENT)/source/Sources"); - Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::flatURI", "Sources"); + Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::MetaKey", "$(COMPONENT)/source/Sources"); + Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::flatMetaKey", "Sources"); Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::ShortDescription", "Sources"); Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::Description", "$(SITE) $(RELEASE)/$(COMPONENT) Sources"); Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::flatDescription", "$(SITE) $(RELEASE) Sources"); -- cgit v1.2.3 From dcbbb14df8c9a8a146697720874e9425c4b33792 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 10 Jun 2015 22:10:48 +0200 Subject: stop using IndexTarget pointers which are never freed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Creating and passing around a bunch of pointers of IndexTargets (and of a vector of pointers of IndexTargets) is probably done to avoid the 'costly' copy of container, but we are really not in a timecritical operation here and move semantics will help us even further in the future. On the other hand we never do a proper cleanup of these pointers, which is very dirty, even if structures aren't that big… The changes will effecting many items only effect our own hidden class, so we can do that without fearing breaking interfaces or anything. Git-Dch: Ignore --- apt-pkg/acquire-item.cc | 167 ++++++++++++++++++++++---------------------- apt-pkg/acquire-item.h | 46 ++++++------ apt-pkg/deb/debmetaindex.cc | 16 ++--- apt-pkg/deb/debmetaindex.h | 2 +- 4 files changed, 113 insertions(+), 118 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index e92ccc08b..05ea9c069 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -191,7 +191,7 @@ HashStringList pkgAcqIndexMergeDiffs::GetExpectedHashes() const if (State == StateFetchDiff) return patch.download_hashes; else if (State == StateApplyDiff) - return GetExpectedHashesFor(Target->MetaKey); + return GetExpectedHashesFor(Target.MetaKey); return HashStringList(); } @@ -266,20 +266,20 @@ std::string pkgAcqDiffIndex::GetFinalFilename() const } std::string pkgAcqIndex::GetFinalFilename() const { - std::string const FinalFile = GetFinalFileNameFromURI(Target->URI); - return GetCompressedFileName(Target->URI, FinalFile, CurrentCompressionExtension); + std::string const FinalFile = GetFinalFileNameFromURI(Target.URI); + return GetCompressedFileName(Target.URI, FinalFile, CurrentCompressionExtension); } std::string pkgAcqMetaSig::GetFinalFilename() const { - return GetFinalFileNameFromURI(Target->URI); + return GetFinalFileNameFromURI(Target.URI); } std::string pkgAcqBaseIndex::GetFinalFilename() const { - return GetFinalFileNameFromURI(Target->URI); + return GetFinalFileNameFromURI(Target.URI); } std::string pkgAcqMetaBase::GetFinalFilename() const { - return GetFinalFileNameFromURI(DataTarget.URI); + return GetFinalFileNameFromURI(Target.URI); } std::string pkgAcqArchive::GetFinalFilename() const { @@ -289,17 +289,17 @@ std::string pkgAcqArchive::GetFinalFilename() const // pkgAcqTransactionItem::GetMetaKey and specialisations for child classes /*{{{*/ std::string pkgAcqTransactionItem::GetMetaKey() const { - return Target->MetaKey; + return Target.MetaKey; } std::string pkgAcqIndex::GetMetaKey() const { if (Stage == STAGE_DECOMPRESS_AND_VERIFY || CurrentCompressionExtension == "uncompressed") - return Target->MetaKey; - return Target->MetaKey + "." + CurrentCompressionExtension; + return Target.MetaKey; + return Target.MetaKey + "." + CurrentCompressionExtension; } std::string pkgAcqDiffIndex::GetMetaKey() const { - return Target->MetaKey + ".diff/Index"; + return Target.MetaKey + ".diff/Index"; } /*}}}*/ //pkgAcqTransactionItem::TransactionState and specialisations for child classes /*{{{*/ @@ -373,7 +373,7 @@ bool pkgAcqDiffIndex::TransactionState(TransactionStates const state) case TransactionCommit: break; case TransactionAbort: - std::string const Partial = GetPartialFileNameFromURI(Target->URI); + std::string const Partial = GetPartialFileNameFromURI(Target.URI); unlink(Partial.c_str()); break; } @@ -396,16 +396,16 @@ class APT_HIDDEN NoActionItem : public pkgAcquire::Item /*{{{*/ reach its done state to prevent cleanup deleting the mentioned file. Handy in cases in which we know we have the file already, like IMS-Hits. */ { - IndexTarget const * const Target; + IndexTarget const Target; public: - virtual std::string DescURI() const {return Target->URI;}; + virtual std::string DescURI() const {return Target.URI;}; virtual HashStringList GetExpectedHashes() const {return HashStringList();}; - NoActionItem(pkgAcquire * const Owner, IndexTarget const * const Target) : + NoActionItem(pkgAcquire * const Owner, IndexTarget const Target) : pkgAcquire::Item(Owner), Target(Target) { Status = StatDone; - DestFile = GetFinalFileNameFromURI(Target->URI); + DestFile = GetFinalFileNameFromURI(Target.URI); } }; /*}}}*/ @@ -669,7 +669,7 @@ std::string pkgAcquire::Item::HashSum() const /*{{{*/ /*}}}*/ pkgAcqTransactionItem::pkgAcqTransactionItem(pkgAcquire * const Owner, /*{{{*/ - pkgAcqMetaBase * const TransactionManager, IndexTarget const * const Target) : + pkgAcqMetaBase * const TransactionManager, IndexTarget const Target) : pkgAcquire::Item(Owner), Target(Target), TransactionManager(TransactionManager) { if (TransactionManager != this) @@ -689,10 +689,10 @@ HashStringList pkgAcqTransactionItem::GetExpectedHashesFor(std::string const Met // AcqMetaBase - Constructor /*{{{*/ pkgAcqMetaBase::pkgAcqMetaBase(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, - std::vector const * const IndexTargets, + std::vector const IndexTargets, IndexTarget const &DataTarget, indexRecords * const MetaIndexParser) -: pkgAcqTransactionItem(Owner, TransactionManager, NULL), DataTarget(DataTarget), +: pkgAcqTransactionItem(Owner, TransactionManager, DataTarget), MetaIndexParser(MetaIndexParser), LastMetaIndexParser(NULL), IndexTargets(IndexTargets), AuthPass(false), IMSHit(false) { @@ -953,31 +953,30 @@ void pkgAcqMetaBase::QueueIndexes(bool const verify) /*{{{*/ // at this point the real Items are loaded in the fetcher ExpectedAdditionalItems = 0; - vector ::const_iterator Target; - for (Target = IndexTargets->begin(); - Target != IndexTargets->end(); + for (std::vector ::const_iterator Target = IndexTargets.begin(); + Target != IndexTargets.end(); ++Target) { bool trypdiff = _config->FindB("Acquire::PDiffs", true); if (verify == true) { - if (TransactionManager->MetaIndexParser->Exists((*Target)->MetaKey) == false) + if (TransactionManager->MetaIndexParser->Exists(Target->MetaKey) == false) { // optional targets that we do not have in the Release file are skipped - if ((*Target)->IsOptional) + if (Target->IsOptional) continue; Status = StatAuthError; - strprintf(ErrorText, _("Unable to find expected entry '%s' in Release file (Wrong sources.list entry or malformed file)"), (*Target)->MetaKey.c_str()); + strprintf(ErrorText, _("Unable to find expected entry '%s' in Release file (Wrong sources.list entry or malformed file)"), Target->MetaKey.c_str()); return; } - if (RealFileExists(GetFinalFileNameFromURI((*Target)->URI))) + if (RealFileExists(GetFinalFileNameFromURI(Target->URI))) { if (TransactionManager->LastMetaIndexParser != NULL) { - HashStringList const newFile = GetExpectedHashesFromFor(TransactionManager->MetaIndexParser, (*Target)->MetaKey); - HashStringList const oldFile = GetExpectedHashesFromFor(TransactionManager->LastMetaIndexParser, (*Target)->MetaKey); + HashStringList const newFile = GetExpectedHashesFromFor(TransactionManager->MetaIndexParser, Target->MetaKey); + HashStringList const oldFile = GetExpectedHashesFromFor(TransactionManager->LastMetaIndexParser, Target->MetaKey); if (newFile == oldFile) { // we have the file already, no point in trying to acquire it again @@ -990,15 +989,15 @@ void pkgAcqMetaBase::QueueIndexes(bool const verify) /*{{{*/ trypdiff = false; // no file to patch // check if we have patches available - trypdiff &= TransactionManager->MetaIndexParser->Exists((*Target)->MetaKey + ".diff/Index"); + trypdiff &= TransactionManager->MetaIndexParser->Exists(Target->MetaKey + ".diff/Index"); } // if we have no file to patch, no point in trying - trypdiff &= RealFileExists(GetFinalFileNameFromURI((*Target)->URI)); + trypdiff &= RealFileExists(GetFinalFileNameFromURI(Target->URI)); // no point in patching from local sources if (trypdiff) { - std::string const proto = (*Target)->URI.substr(0, strlen("file:/")); + std::string const proto = Target->URI.substr(0, strlen("file:/")); if (proto == "file:/" || proto == "copy:/" || proto == "cdrom:") trypdiff = false; } @@ -1060,7 +1059,7 @@ bool pkgAcqMetaBase::VerifyVendor(string const &Message) /*{{{*/ // the download progress display (e.g. 7d 3h 42min 1s) _("Release file for %s is expired (invalid since %s). " "Updates for this repository will not be applied."), - DataTarget.URI.c_str(), TimeToStr(invalid_since).c_str()); + Target.URI.c_str(), TimeToStr(invalid_since).c_str()); if (ErrorText.empty()) ErrorText = errmsg; return _error->Error("%s", errmsg.c_str()); @@ -1111,14 +1110,14 @@ bool pkgAcqMetaBase::VerifyVendor(string const &Message) /*{{{*/ pkgAcqMetaClearSig::pkgAcqMetaClearSig(pkgAcquire * const Owner, /*{{{*/ IndexTarget const &ClearsignedTarget, IndexTarget const &DetachedDataTarget, IndexTarget const &DetachedSigTarget, - const vector* const IndexTargets, + std::vector const IndexTargets, indexRecords * const MetaIndexParser) : pkgAcqMetaIndex(Owner, this, ClearsignedTarget, DetachedSigTarget, IndexTargets, MetaIndexParser), ClearsignedTarget(ClearsignedTarget), DetachedDataTarget(DetachedDataTarget), DetachedSigTarget(DetachedSigTarget) { // index targets + (worst case:) Release/Release.gpg - ExpectedAdditionalItems = IndexTargets->size() + 2; + ExpectedAdditionalItems = IndexTargets.size() + 2; TransactionManager->Add(this); } /*}}}*/ @@ -1167,8 +1166,8 @@ void pkgAcqMetaClearSig::Done(std::string const &Message, // We got an InRelease file IMSHit, but we haven't one, which means // we had a valid Release/Release.gpg combo stepping in, which we have // to 'acquire' now to ensure list cleanup isn't removing them - new NoActionItem(Owner, &DetachedDataTarget); - new NoActionItem(Owner, &DetachedSigTarget); + new NoActionItem(Owner, DetachedDataTarget); + new NoActionItem(Owner, DetachedSigTarget); } } } @@ -1251,7 +1250,7 @@ pkgAcqMetaIndex::pkgAcqMetaIndex(pkgAcquire * const Owner, /*{{{*/ pkgAcqMetaBase * const TransactionManager, IndexTarget const &DataTarget, IndexTarget const &DetachedSigTarget, - vector const * const IndexTargets, + vector const IndexTargets, indexRecords * const MetaIndexParser) : pkgAcqMetaBase(Owner, TransactionManager, IndexTargets, DataTarget, MetaIndexParser), DetachedSigTarget(DetachedSigTarget) @@ -1269,7 +1268,7 @@ pkgAcqMetaIndex::pkgAcqMetaIndex(pkgAcquire * const Owner, /*{{{*/ Desc.URI = DataTarget.URI; // we expect more item - ExpectedAdditionalItems = IndexTargets->size(); + ExpectedAdditionalItems = IndexTargets.size(); QueueURI(Desc); } /*}}}*/ @@ -1284,7 +1283,7 @@ void pkgAcqMetaIndex::Done(string const &Message, /*{{{*/ // we have a Release file, now download the Signature, all further // verify/queue for additional downloads will be done in the // pkgAcqMetaSig::Done() code - new pkgAcqMetaSig(Owner, TransactionManager, &DetachedSigTarget, this); + new pkgAcqMetaSig(Owner, TransactionManager, DetachedSigTarget, this); } } /*}}}*/ @@ -1297,7 +1296,7 @@ void pkgAcqMetaIndex::Failed(string const &Message, _error->Warning(_("The repository '%s' does not have a Release file. " "This is deprecated, please contact the owner of the " - "repository."), DataTarget.Description.c_str()); + "repository."), Target.Description.c_str()); // No Release file was present so fall // back to queueing Packages files without verification @@ -1325,18 +1324,18 @@ void pkgAcqMetaIndex::Finished() /*{{{*/ /*}}}*/ std::string pkgAcqMetaIndex::DescURI() const /*{{{*/ { - return DataTarget.URI; + return Target.URI; } /*}}}*/ // AcqMetaSig::AcqMetaSig - Constructor /*{{{*/ pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, - IndexTarget const * const Target, + IndexTarget const Target, pkgAcqMetaIndex * const MetaIndex) : pkgAcqTransactionItem(Owner, TransactionManager, Target), MetaIndex(MetaIndex) { - DestFile = GetPartialFileNameFromURI(Target->URI); + DestFile = GetPartialFileNameFromURI(Target.URI); // remove any partial downloaded sig-file in partial/. // it may confuse proxies and is too small to warrant a @@ -1349,10 +1348,10 @@ pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire * const Owner, << TransactionManager << std::endl; // Create the item - Desc.Description = Target->Description; + Desc.Description = Target.Description; Desc.Owner = this; - Desc.ShortDesc = Target->ShortDesc; - Desc.URI = Target->URI; + Desc.ShortDesc = Target.ShortDesc; + Desc.URI = Target.URI; // If we got a hit for Release, we will get one for Release.gpg too (or obscure errors), // so we skip the download step and go instantly to verification @@ -1420,7 +1419,7 @@ void pkgAcqMetaSig::Failed(string const &Message,pkgAcquire::MethodConfig const { std::string downgrade_msg; strprintf(downgrade_msg, _("The repository '%s' is no longer signed."), - MetaIndex->DataTarget.Description.c_str()); + MetaIndex->Target.Description.c_str()); if(_config->FindB("Acquire::AllowDowngradeToInsecureRepositories")) { // meh, the users wants to take risks (we still mark the packages @@ -1442,7 +1441,7 @@ void pkgAcqMetaSig::Failed(string const &Message,pkgAcquire::MethodConfig const else _error->Warning(_("The data from '%s' is not signed. Packages " "from that repository can not be authenticated."), - MetaIndex->DataTarget.Description.c_str()); + MetaIndex->Target.Description.c_str()); // ensures that a Release.gpg file in the lists/ is removed by the transaction TransactionManager->TransactionStageRemoval(this, DestFile); @@ -1495,7 +1494,7 @@ void pkgAcqMetaSig::Failed(string const &Message,pkgAcquire::MethodConfig const // AcqBaseIndex - Constructor /*{{{*/ pkgAcqBaseIndex::pkgAcqBaseIndex(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, - IndexTarget const * const Target) + IndexTarget const Target) : pkgAcqTransactionItem(Owner, TransactionManager, Target) { } @@ -1510,15 +1509,15 @@ pkgAcqBaseIndex::pkgAcqBaseIndex(pkgAcquire * const Owner, */ pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, - IndexTarget const * const Target) + IndexTarget const Target) : pkgAcqBaseIndex(Owner, TransactionManager, Target) { Debug = _config->FindB("Debug::pkgAcquire::Diffs",false); Desc.Owner = this; - Desc.Description = Target->Description + ".diff/Index"; - Desc.ShortDesc = Target->ShortDesc; - Desc.URI = Target->URI + ".diff/Index"; + Desc.Description = Target.Description + ".diff/Index"; + Desc.ShortDesc = Target.ShortDesc; + Desc.URI = Target.URI + ".diff/Index"; DestFile = GetPartialFileNameFromURI(Desc.URI); @@ -1599,8 +1598,8 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string const &IndexDiffFile) /*{{{*/ return false; } - std::string const CurrentPackagesFile = GetFinalFileNameFromURI(Target->URI); - HashStringList const TargetFileHashes = GetExpectedHashesFor(Target->MetaKey); + std::string const CurrentPackagesFile = GetFinalFileNameFromURI(Target.URI); + HashStringList const TargetFileHashes = GetExpectedHashesFor(Target.MetaKey); if (TargetFileHashes.usable() == false || ServerHashes != TargetFileHashes) { if (Debug == true) @@ -1614,7 +1613,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string const &IndexDiffFile) /*{{{*/ HashStringList LocalHashes; // try avoiding calculating the hash here as this is costly if (TransactionManager->LastMetaIndexParser != NULL) - LocalHashes = GetExpectedHashesFromFor(TransactionManager->LastMetaIndexParser, Target->MetaKey); + LocalHashes = GetExpectedHashesFromFor(TransactionManager->LastMetaIndexParser, Target.MetaKey); if (LocalHashes.usable() == false) { FileFd fd(CurrentPackagesFile, FileFd::ReadOnly); @@ -1910,29 +1909,29 @@ void pkgAcqDiffIndex::Done(string const &Message,HashStringList const &Hashes, / */ pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, - IndexTarget const * const Target, + IndexTarget const Target, vector const &diffs) : pkgAcqBaseIndex(Owner, TransactionManager, Target), available_patches(diffs) { - DestFile = GetPartialFileNameFromURI(Target->URI); + DestFile = GetPartialFileNameFromURI(Target.URI); Debug = _config->FindB("Debug::pkgAcquire::Diffs",false); Desc.Owner = this; - Description = Target->Description; - Desc.ShortDesc = Target->ShortDesc; + Description = Target.Description; + Desc.ShortDesc = Target.ShortDesc; if(available_patches.empty() == true) { // we are done (yeah!), check hashes against the final file - DestFile = GetFinalFileNameFromURI(Target->URI); + DestFile = GetFinalFileNameFromURI(Target.URI); Finish(true); } else { // patching needs to be bootstrapped with the 'old' version - std::string const PartialFile = GetPartialFileNameFromURI(Target->URI); + std::string const PartialFile = GetPartialFileNameFromURI(Target.URI); if (RealFileExists(PartialFile) == false) { if (symlink(GetFinalFilename().c_str(), PartialFile.c_str()) != 0) @@ -1956,7 +1955,7 @@ void pkgAcqIndexDiffs::Failed(string const &Message,pkgAcquire::MethodConfig con if(Debug) std::clog << "pkgAcqIndexDiffs failed: " << Desc.URI << " with " << Message << std::endl << "Falling back to normal index file acquire" << std::endl; - DestFile = GetPartialFileNameFromURI(Target->URI); + DestFile = GetPartialFileNameFromURI(Target.URI); RenameOnError(PDiffError); std::string const patchname = GetDiffsPatchFileName(DestFile); if (RealFileExists(patchname)) @@ -1999,7 +1998,7 @@ void pkgAcqIndexDiffs::Finish(bool allDone) bool pkgAcqIndexDiffs::QueueNextDiff() /*{{{*/ { // calc sha1 of the just patched file - std::string const FinalFile = GetPartialFileNameFromURI(Target->URI); + std::string const FinalFile = GetPartialFileNameFromURI(Target.URI); if(!FileExists(FinalFile)) { @@ -2015,7 +2014,7 @@ bool pkgAcqIndexDiffs::QueueNextDiff() /*{{{*/ if(Debug) std::clog << "QueueNextDiff: " << FinalFile << " (" << LocalHashes.find(NULL)->toStr() << ")" << std::endl; - HashStringList const TargetFileHashes = GetExpectedHashesFor(Target->MetaKey); + HashStringList const TargetFileHashes = GetExpectedHashesFor(Target.MetaKey); if (unlikely(LocalHashes.usable() == false || TargetFileHashes.usable() == false)) { Failed("Local/Expected hashes are not usable", NULL); @@ -2049,9 +2048,9 @@ bool pkgAcqIndexDiffs::QueueNextDiff() /*{{{*/ } // queue the right diff - Desc.URI = Target->URI + ".diff/" + available_patches[0].file + ".gz"; + Desc.URI = Target.URI + ".diff/" + available_patches[0].file + ".gz"; Desc.Description = Description + " " + available_patches[0].file + string(".pdiff"); - DestFile = GetPartialFileNameFromURI(Target->URI + ".diff/" + available_patches[0].file); + DestFile = GetPartialFileNameFromURI(Target.URI + ".diff/" + available_patches[0].file); if(Debug) std::clog << "pkgAcqIndexDiffs::QueueNextDiff(): " << Desc.URI << std::endl; @@ -2069,7 +2068,7 @@ void pkgAcqIndexDiffs::Done(string const &Message, HashStringList const &Hashes, Item::Done(Message, Hashes, Cnf); - std::string const FinalFile = GetPartialFileNameFromURI(Target->URI); + std::string const FinalFile = GetPartialFileNameFromURI(Target.URI); std::string const PatchFile = GetDiffsPatchFileName(FinalFile); // success in downloading a diff, enter ApplyDiff state @@ -2132,7 +2131,7 @@ std::string pkgAcqIndexDiffs::Custom600Headers() const /*{{{*/ // AcqIndexMergeDiffs::AcqIndexMergeDiffs - Constructor /*{{{*/ pkgAcqIndexMergeDiffs::pkgAcqIndexMergeDiffs(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, - IndexTarget const * const Target, + IndexTarget const Target, DiffInfo const &patch, std::vector const * const allPatches) : pkgAcqBaseIndex(Owner, TransactionManager, Target), @@ -2141,13 +2140,13 @@ pkgAcqIndexMergeDiffs::pkgAcqIndexMergeDiffs(pkgAcquire * const Owner, Debug = _config->FindB("Debug::pkgAcquire::Diffs",false); Desc.Owner = this; - Description = Target->Description; - Desc.ShortDesc = Target->ShortDesc; + Description = Target.Description; + Desc.ShortDesc = Target.ShortDesc; - Desc.URI = Target->URI + ".diff/" + patch.file + ".gz"; + Desc.URI = Target.URI + ".diff/" + patch.file + ".gz"; Desc.Description = Description + " " + patch.file + string(".pdiff"); - DestFile = GetPartialFileNameFromURI(Target->URI + ".diff/" + patch.file); + DestFile = GetPartialFileNameFromURI(Target.URI + ".diff/" + patch.file); if(Debug) std::clog << "pkgAcqIndexMergeDiffs: " << Desc.URI << std::endl; @@ -2174,7 +2173,7 @@ void pkgAcqIndexMergeDiffs::Failed(string const &Message,pkgAcquire::MethodConfi State = StateErrorDiff; if (Debug) std::clog << "Falling back to normal index file acquire" << std::endl; - DestFile = GetPartialFileNameFromURI(Target->URI); + DestFile = GetPartialFileNameFromURI(Target.URI); RenameOnError(PDiffError); std::string const patchname = GetMergeDiffsPatchFileName(DestFile, patch.file); if (RealFileExists(patchname)) @@ -2190,7 +2189,7 @@ void pkgAcqIndexMergeDiffs::Done(string const &Message, HashStringList const &Ha Item::Done(Message, Hashes, Cnf); - string const FinalFile = GetPartialFileNameFromURI(Target->URI); + string const FinalFile = GetPartialFileNameFromURI(Target.URI); if (State == StateFetchDiff) { Rename(DestFile, GetMergeDiffsPatchFileName(FinalFile, patch.file)); @@ -2241,7 +2240,7 @@ void pkgAcqIndexMergeDiffs::Done(string const &Message, HashStringList const &Ha for (std::vector::const_iterator I = allPatches->begin(); I != allPatches->end(); ++I) { - std::string const PartialFile = GetPartialFileNameFromURI(Target->URI); + std::string const PartialFile = GetPartialFileNameFromURI(Target.URI); std::string const patch = GetMergeDiffsPatchFileName(PartialFile, (*I)->patch.file); unlink(patch.c_str()); } @@ -2276,12 +2275,12 @@ std::string pkgAcqIndexMergeDiffs::Custom600Headers() const /*{{{*/ // AcqIndex::AcqIndex - Constructor /*{{{*/ pkgAcqIndex::pkgAcqIndex(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, - IndexTarget const * const Target) + IndexTarget const Target) : pkgAcqBaseIndex(Owner, TransactionManager, Target) { // 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 " @@ -2293,12 +2292,12 @@ void pkgAcqIndex::AutoSelectCompression() { std::vector types = APT::Configuration::getCompressionTypes(); CompressionExtensions = ""; - if (TransactionManager->MetaIndexParser != NULL && TransactionManager->MetaIndexParser->Exists(Target->MetaKey)) + if (TransactionManager->MetaIndexParser != NULL && TransactionManager->MetaIndexParser->Exists(Target.MetaKey)) { for (std::vector::const_iterator t = types.begin(); t != types.end(); ++t) { - std::string CompressedMetaKey = string(Target->MetaKey).append(".").append(*t); + std::string CompressedMetaKey = string(Target.MetaKey).append(".").append(*t); if (*t == "uncompressed" || TransactionManager->MetaIndexParser->Exists(CompressedMetaKey) == true) CompressionExtensions.append(*t).append(" "); @@ -2397,7 +2396,7 @@ string pkgAcqIndex::Custom600Headers() const 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; @@ -2413,13 +2412,13 @@ void pkgAcqIndex::Failed(string const &Message,pkgAcquire::MethodConfig const * { if (CompressionExtensions.empty() == false) { - Init(Target->URI, Desc.Description, Desc.ShortDesc); + Init(Target.URI, Desc.Description, Desc.ShortDesc); Status = StatIdle; return; } } - if(Target->IsOptional && GetExpectedHashes().empty() && Stage == STAGE_DOWNLOAD) + if(Target.IsOptional && GetExpectedHashes().empty() && Stage == STAGE_DOWNLOAD) Status = StatDone; else TransactionManager->AbortTransaction(); @@ -2430,7 +2429,7 @@ void pkgAcqIndex::ReverifyAfterIMS() { // update destfile to *not* include the compression extension when doing // a reverify (as its uncompressed on disk already) - DestFile = GetCompressedFileName(Target->URI, GetPartialFileNameFromURI(Target->URI), CurrentCompressionExtension); + DestFile = GetCompressedFileName(Target.URI, GetPartialFileNameFromURI(Target.URI), CurrentCompressionExtension); // copy FinalFile into partial/ so that we check the hash again string FinalFile = GetFinalFilename(); @@ -2509,7 +2508,7 @@ void pkgAcqIndex::StageDownloadDone(string const &Message, HashStringList const // If we have compressed indexes enabled, queue for hash verification if (_config->FindB("Acquire::GzipIndexes",false)) { - DestFile = GetPartialFileNameFromURI(Target->URI + '.' + CurrentCompressionExtension); + DestFile = GetPartialFileNameFromURI(Target.URI + '.' + CurrentCompressionExtension); EraseFileName = ""; Stage = STAGE_DECOMPRESS_AND_VERIFY; Desc.URI = "copy:" + FileName; diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index a2571e1cd..790d1f3d8 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -55,23 +55,23 @@ class IndexTarget /*{{{*/ { public: /** \brief A URI from which the index file can be downloaded. */ - std::string const URI; + std::string URI; /** \brief A description of the index file. */ - std::string const Description; + std::string Description; /** \brief A shorter description of the index file. */ - std::string const ShortDesc; + std::string ShortDesc; /** \brief The key by which this index file should be looked up within the meta index file. */ - std::string const MetaKey; + std::string MetaKey; /** \brief Is it okay if the file isn't found in the meta index */ - bool const IsOptional; + bool IsOptional; /** \brief Target specific options defined by the implementation */ - std::map const Options; + std::map Options; IndexTarget(std::string const &MetaKey, std::string const &ShortDesc, std::string const &LongDesc, std::string const &URI, bool const IsOptional, @@ -374,7 +374,7 @@ class APT_HIDDEN pkgAcqTransactionItem: public pkgAcquire::Item /*{{{*/ /** \brief baseclass for the indexes files to manage them all together */ { protected: - IndexTarget const * const Target; + IndexTarget const Target; HashStringList GetExpectedHashesFor(std::string const MetaKey) const; bool QueueURI(pkgAcquire::ItemDesc &Item); @@ -392,13 +392,13 @@ class APT_HIDDEN pkgAcqTransactionItem: public pkgAcquire::Item /*{{{*/ }; virtual bool TransactionState(TransactionStates const state); - virtual std::string DescURI() const { return Target->URI; } + virtual std::string DescURI() const { return Target.URI; } virtual HashStringList GetExpectedHashes() const; virtual std::string GetMetaKey() const; virtual bool HashesRequired() const; - pkgAcqTransactionItem(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, IndexTarget const * const Target); + pkgAcqTransactionItem(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, IndexTarget const Target); virtual ~pkgAcqTransactionItem(); friend class pkgAcqMetaBase; @@ -412,7 +412,6 @@ class APT_HIDDEN pkgAcqMetaBase : public pkgAcqTransactionItem /*{{{*/ protected: std::vector Transaction; - IndexTarget const DataTarget; public: /** \brief A package-system-specific parser for the meta-index file. */ indexRecords *MetaIndexParser; @@ -422,7 +421,7 @@ class APT_HIDDEN pkgAcqMetaBase : public pkgAcqTransactionItem /*{{{*/ /** \brief The index files which should be looked up in the meta-index * and then downloaded. */ - const std::vector* const IndexTargets; + std::vector const IndexTargets; /** \brief If \b true, the index's signature is currently being verified. */ @@ -504,7 +503,7 @@ class APT_HIDDEN pkgAcqMetaBase : public pkgAcqTransactionItem /*{{{*/ virtual std::string GetFinalFilename() const; pkgAcqMetaBase(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, - std::vector const * const IndexTargets, + std::vector const IndexTargets, IndexTarget const &DataTarget, indexRecords* const MetaIndexParser); }; @@ -541,7 +540,7 @@ class APT_HIDDEN pkgAcqMetaIndex : public pkgAcqMetaBase /** \brief Create a new pkgAcqMetaIndex. */ pkgAcqMetaIndex(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, IndexTarget const &DataTarget, IndexTarget const &DetachedSigTarget, - const std::vector* const IndexTargets, indexRecords * const MetaIndexParser); + std::vector const IndexTargets, indexRecords * const MetaIndexParser); friend class pkgAcqMetaSig; }; @@ -577,7 +576,7 @@ class APT_HIDDEN pkgAcqMetaSig : public pkgAcqTransactionItem pkgAcquire::MethodConfig const * const Cnf); /** \brief Create a new pkgAcqMetaSig. */ - pkgAcqMetaSig(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, IndexTarget const * const Target, + pkgAcqMetaSig(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, IndexTarget const Target, pkgAcqMetaIndex * const MetaIndex); virtual ~pkgAcqMetaSig(); }; @@ -602,7 +601,7 @@ public: IndexTarget const &ClearsignedTarget, IndexTarget const &DetachedDataTarget, IndexTarget const &DetachedSigTarget, - std::vector const * const IndexTargets, + std::vector const IndexTargets, indexRecords * const MetaIndexParser); virtual ~pkgAcqMetaClearSig(); }; @@ -617,7 +616,7 @@ class APT_HIDDEN pkgAcqBaseIndex : public pkgAcqTransactionItem virtual std::string GetFinalFilename() const; pkgAcqBaseIndex(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, - IndexTarget const * const Target); + IndexTarget const Target); }; /*}}}*/ /** \brief An item that is responsible for fetching an index file of {{{ @@ -653,7 +652,7 @@ class APT_HIDDEN pkgAcqDiffIndex : public pkgAcqBaseIndex virtual void Failed(std::string const &Message, pkgAcquire::MethodConfig const * const Cnf); virtual void Done(std::string const &Message, HashStringList const &Hashes, pkgAcquire::MethodConfig const * const Cnf); - virtual std::string DescURI() const {return Target->URI + "Index";}; + virtual std::string DescURI() const {return Target.URI + "Index";}; virtual std::string Custom600Headers() const; virtual std::string GetMetaKey() const; @@ -680,7 +679,7 @@ class APT_HIDDEN pkgAcqDiffIndex : public pkgAcqBaseIndex * \param ShortDesc A short description of the list file to download. */ pkgAcqDiffIndex(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, - IndexTarget const * const Target); + IndexTarget const Target); private: APT_HIDDEN void QueueOnIMSHit() const; }; @@ -756,7 +755,7 @@ class APT_HIDDEN pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex virtual void Done(std::string const &Message, HashStringList const &Hashes, pkgAcquire::MethodConfig const * const Cnf); virtual std::string Custom600Headers() const; - virtual std::string DescURI() const {return Target->URI + "Index";}; + virtual std::string DescURI() const {return Target.URI + "Index";}; virtual HashStringList GetExpectedHashes() const; virtual bool HashesRequired() const; @@ -778,8 +777,7 @@ class APT_HIDDEN pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex * check if it was the last one to complete the download step */ pkgAcqIndexMergeDiffs(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, - IndexTarget const * const Target, - DiffInfo const &patch, + IndexTarget const Target, DiffInfo const &patch, std::vector const * const allPatches); }; /*}}}*/ @@ -869,7 +867,7 @@ class APT_HIDDEN pkgAcqIndexDiffs : public pkgAcqBaseIndex virtual void Done(std::string const &Message, HashStringList const &Hashes, pkgAcquire::MethodConfig const * const Cnf); virtual std::string Custom600Headers() const; - virtual std::string DescURI() const {return Target->URI + "IndexDiffs";}; + virtual std::string DescURI() const {return Target.URI + "IndexDiffs";}; virtual HashStringList GetExpectedHashes() const; virtual bool HashesRequired() const; @@ -892,7 +890,7 @@ class APT_HIDDEN pkgAcqIndexDiffs : public pkgAcqBaseIndex * that depends on it. */ pkgAcqIndexDiffs(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, - IndexTarget const * const Target, + IndexTarget const Target, std::vector const &diffs=std::vector()); }; /*}}}*/ @@ -969,7 +967,7 @@ class APT_HIDDEN pkgAcqIndex : public pkgAcqBaseIndex virtual std::string GetMetaKey() const; pkgAcqIndex(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, - IndexTarget const * const Target); + IndexTarget const Target); void Init(std::string const &URI, std::string const &URIDesc, std::string const &ShortDesc); diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index f038f12f5..44d66a725 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -93,7 +93,7 @@ debReleaseIndex::~debReleaseIndex() { template void foreachTarget(std::string const URI, std::string const Dist, std::map > const &ArchEntries, - CallC Call) + CallC &Call) { bool const flatArchive = (Dist[Dist.length() - 1] == '/'); std::string baseURI = URI; @@ -206,7 +206,7 @@ void foreachTarget(std::string const URI, std::string const Dist, struct ComputeIndexTargetsClass { - vector * const IndexTargets; + vector IndexTargets; void operator()(std::string MetaKey, std::string ShortDesc, std::string LongDesc, bool const IsOptional, std::map Options) @@ -217,7 +217,7 @@ struct ComputeIndexTargetsClass ShortDesc = SubstVar(ShortDesc, std::string("$(") + O->first + ")", O->second); LongDesc = SubstVar(LongDesc, std::string("$(") + O->first + ")", O->second); } - IndexTarget * Target = new IndexTarget( + IndexTarget Target( MetaKey, ShortDesc, LongDesc, @@ -225,13 +225,11 @@ struct ComputeIndexTargetsClass IsOptional, Options ); - IndexTargets->push_back(Target); + IndexTargets.push_back(Target); } - - ComputeIndexTargetsClass() : IndexTargets(new vector ) {} }; -vector * debReleaseIndex::ComputeIndexTargets() const +std::vector debReleaseIndex::ComputeIndexTargets() const { ComputeIndexTargetsClass comp; foreachTarget(URI, Dist, ArchEntries, comp); @@ -249,7 +247,7 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const iR->SetTrusted(false); // special case for --print-uris - vector const * const targets = ComputeIndexTargets(); + std::vector const targets = ComputeIndexTargets(); #define APT_TARGET(X) IndexTarget("", X, MetaIndexInfo(X), MetaIndexURI(X), false, std::map()) pkgAcqMetaBase * const TransactionManager = new pkgAcqMetaClearSig(Owner, APT_TARGET("InRelease"), APT_TARGET("Release"), APT_TARGET("Release.gpg"), @@ -257,7 +255,7 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const #undef APT_TARGET if (GetAll) { - for (vector ::const_iterator Target = targets->begin(); Target != targets->end(); ++Target) + for (std::vector::const_iterator Target = targets.begin(); Target != targets.end(); ++Target) new pkgAcqIndex(Owner, TransactionManager, *Target); } diff --git a/apt-pkg/deb/debmetaindex.h b/apt-pkg/deb/debmetaindex.h index e1c1d91ef..4e630cf5d 100644 --- a/apt-pkg/deb/debmetaindex.h +++ b/apt-pkg/deb/debmetaindex.h @@ -46,7 +46,7 @@ class APT_HIDDEN debReleaseIndex : public metaIndex { virtual std::string ArchiveURI(std::string const &File) const {return URI + File;}; virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false) const; - std::vector * ComputeIndexTargets() const; + std::vector ComputeIndexTargets() const; std::string MetaIndexInfo(const char *Type) const; std::string MetaIndexFile(const char *Types) const; -- cgit v1.2.3 From 261727f05ca7ff7d9d6d9b8927cb5c6ad293ebce Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 10 Jun 2015 23:53:36 +0200 Subject: rename Calculate- to GetIndexTargets and use it as official API We need a general way to get from a sources.list entry to IndexTargets and with this change we can move from pkgSourceList over the list of metaIndexes it includes to the IndexTargets each metaIndex can have. Git-Dch: Ignore --- apt-pkg/deb/debmetaindex.cc | 37 +++++++++++++++---------------------- apt-pkg/deb/debmetaindex.h | 5 ++++- apt-pkg/metaindex.h | 6 ++---- 3 files changed, 21 insertions(+), 27 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 44d66a725..e1f86d20f 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -229,7 +229,7 @@ struct ComputeIndexTargetsClass } }; -std::vector debReleaseIndex::ComputeIndexTargets() const +std::vector debReleaseIndex::GetIndexTargets() const { ComputeIndexTargetsClass comp; foreachTarget(URI, Dist, ArchEntries, comp); @@ -247,7 +247,7 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const iR->SetTrusted(false); // special case for --print-uris - std::vector const targets = ComputeIndexTargets(); + std::vector const targets = GetIndexTargets(); #define APT_TARGET(X) IndexTarget("", X, MetaIndexInfo(X), MetaIndexURI(X), false, std::map()) pkgAcqMetaBase * const TransactionManager = new pkgAcqMetaClearSig(Owner, APT_TARGET("InRelease"), APT_TARGET("Release"), APT_TARGET("Release.gpg"), @@ -396,6 +396,7 @@ class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type map::const_iterator const trusted = Options.find("trusted"); + debReleaseIndex *Deb = NULL; for (vector::const_iterator I = List.begin(); I != List.end(); ++I) { @@ -403,34 +404,23 @@ class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type 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(*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)); @@ -441,7 +431,10 @@ class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type else Deb->PushSectionEntry (Archs, new debReleaseIndex::debSectionEntry(Section, IsSrc)); } - List.push_back(Deb); + + if (trusted != Options.end()) + Deb->SetTrusted(StringToBool(trusted->second, false)); + return true; } }; diff --git a/apt-pkg/deb/debmetaindex.h b/apt-pkg/deb/debmetaindex.h index 4e630cf5d..0b1b08432 100644 --- a/apt-pkg/deb/debmetaindex.h +++ b/apt-pkg/deb/debmetaindex.h @@ -46,7 +46,7 @@ class APT_HIDDEN debReleaseIndex : public metaIndex { virtual std::string ArchiveURI(std::string const &File) const {return URI + File;}; virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false) const; - std::vector ComputeIndexTargets() const; + virtual std::vector GetIndexTargets() const; std::string MetaIndexInfo(const char *Type) const; std::string MetaIndexFile(const char *Types) const; @@ -78,6 +78,9 @@ class APT_HIDDEN debDebFileMetaIndex : public metaIndex virtual bool GetIndexes(pkgAcquire* /*Owner*/, const bool& /*GetAll=false*/) const { return true; } + virtual std::vector GetIndexTargets() const { + return std::vector(); + } virtual std::vector *GetIndexFiles() { return Indexes; } diff --git a/apt-pkg/metaindex.h b/apt-pkg/metaindex.h index 6c3d2880b..4e5de8be0 100644 --- a/apt-pkg/metaindex.h +++ b/apt-pkg/metaindex.h @@ -22,6 +22,7 @@ using std::string; #endif class pkgAcquire; +class IndexTarget; class metaIndex { @@ -40,16 +41,13 @@ class metaIndex 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 // Interface for acquire virtual std::string ArchiveURI(std::string const& File) const = 0; virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false) const = 0; + virtual std::vector GetIndexTargets() const = 0; virtual std::vector *GetIndexFiles() = 0; virtual bool IsTrusted() const = 0; -- cgit v1.2.3 From 1da3b7b8e15b642135b54684e70a0c271471f07a Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 11 Jun 2015 10:56:31 +0200 Subject: show URI.Path in all acquire item descriptions It is a rather strange sight that index items use SiteOnly which strips the Path, while e.g. deb files are downloaded with NoUserPassword which does not. Important to note here is that for the file transport Path is pretty important as there is no Host which would be displayed by Site, which always resulted in "interesting" unspecific errors for "file:". Adding a 'middle' ground between the two which does show the Path but potentially modifies it (it strips a pending / at the end if existing) solves this "file:" issue, syncs the output and in the end helps to identify which file is meant exactly in progress output and co as a single site can have multiple repositories in different paths. --- apt-pkg/contrib/strutl.cc | 15 +++++++++++---- apt-pkg/contrib/strutl.h | 1 + apt-pkg/deb/debindexfile.cc | 10 +++++----- apt-pkg/deb/debmetaindex.cc | 4 ++-- 4 files changed, 19 insertions(+), 11 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index 0db4c57b2..5731b5a2b 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -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 185248619..20bf5ae50 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -57,7 +57,7 @@ string debSourcesIndex::SourceInfo(pkgSrcRecords::Parser const &Record, pkgSrcRecords::File const &File) const { string Res; - Res = ::URI::NoUserPassword(URI) + ' '; + Res = ::URI::ArchiveOnly(URI) + ' '; if (Dist[Dist.size() - 1] == '/') { if (Dist != "/") @@ -116,7 +116,7 @@ string debSourcesIndex::Describe(bool Short) const /* */ string debSourcesIndex::Info(const char *Type) const { - string Info = ::URI::NoUserPassword(URI) + ' '; + string Info = ::URI::ArchiveOnly(URI) + ' '; if (Dist[Dist.size() - 1] == '/') { if (Dist != "/") @@ -210,7 +210,7 @@ debPackagesIndex::debPackagesIndex(string const &URI, string const &Dist, string /* 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) + ' '; + string Res = ::URI::ArchiveOnly(URI) + ' '; if (Dist[Dist.size() - 1] == '/') { if (Dist != "/") @@ -248,7 +248,7 @@ string debPackagesIndex::Describe(bool Short) const /* */ string debPackagesIndex::Info(const char *Type) const { - string Info = ::URI::NoUserPassword(URI) + ' '; + string Info = ::URI::ArchiveOnly(URI) + ' '; if (Dist[Dist.size() - 1] == '/') { if (Dist != "/") @@ -473,7 +473,7 @@ string debTranslationsIndex::Describe(bool Short) const /* */ string debTranslationsIndex::Info(const char *Type) const { - string Info = ::URI::NoUserPassword(URI) + ' '; + string Info = ::URI::ArchiveOnly(URI) + ' '; if (Dist[Dist.size() - 1] == '/') { if (Dist != "/") diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index e1f86d20f..d4e340be0 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -25,7 +25,7 @@ using namespace std; string debReleaseIndex::MetaIndexInfo(const char *Type) const { - string Info = ::URI::SiteOnly(URI) + ' '; + string Info = ::URI::ArchiveOnly(URI) + ' '; if (Dist[Dist.size() - 1] == '/') { if (Dist != "/") @@ -105,7 +105,7 @@ void foreachTarget(std::string const URI, std::string const Dist, else baseURI += "dists/" + Dist + "/"; std::string const Release = (Dist == "/") ? "" : Dist; - std::string const Site = ::URI::SiteOnly(URI); + std::string const Site = ::URI::ArchiveOnly(URI); std::vector lang = APT::Configuration::getLanguages(true); if (lang.empty()) lang.push_back("none"); -- cgit v1.2.3 From e3c1cfc767f17f5e9b2cd99f2658db3d6ac8edd9 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 11 Jun 2015 11:38:04 +0200 Subject: use IndexTarget to get to IndexFile Removes a bunch of duplicated code in the deb-specific parts. Especially the Description part is now handled centrally by IndexTarget instead of being duplicated to the derivations of IndexFile. Git-Dch: Ignore --- apt-pkg/acquire-item.cc | 9 -- apt-pkg/acquire-item.h | 31 +--- apt-pkg/deb/debindexfile.cc | 381 ++++---------------------------------------- apt-pkg/deb/debindexfile.h | 84 ++-------- apt-pkg/deb/debmetaindex.cc | 56 ++----- apt-pkg/indexfile.cc | 87 +++++++++- apt-pkg/indexfile.h | 58 ++++++- 7 files changed, 197 insertions(+), 509 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 05ea9c069..d4191f00e 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -382,15 +382,6 @@ bool pkgAcqDiffIndex::TransactionState(TransactionStates const state) } /*}}}*/ -// IndexTarget - Constructor /*{{{*/ -IndexTarget::IndexTarget(std::string const &MetaKey, std::string const &ShortDesc, - std::string const &LongDesc, std::string const &URI, bool const IsOptional, - std::map const &Options) : - URI(URI), Description(LongDesc), ShortDesc(ShortDesc), MetaKey(MetaKey), IsOptional(IsOptional), Options(Options) -{ -} - /*}}}*/ - class APT_HIDDEN NoActionItem : public pkgAcquire::Item /*{{{*/ /* The sole purpose of this class is having an item which does nothing to reach its done state to prevent cleanup deleting the mentioned file. diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index 790d1f3d8..b6d569737 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -21,6 +21,7 @@ #define PKGLIB_ACQUIRE_ITEM_H #include +#include #include #include #include @@ -31,7 +32,6 @@ #include #ifndef APT_8_CLEANER_HEADERS -#include #include #include #include @@ -47,37 +47,8 @@ class indexRecords; class pkgRecords; class pkgSourceList; -class IndexTarget; class pkgAcqMetaBase; -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 Target specific options defined by the implementation */ - std::map Options; - - IndexTarget(std::string const &MetaKey, std::string const &ShortDesc, - std::string const &LongDesc, std::string const &URI, bool const IsOptional, - std::map const &Options); -}; - /*}}}*/ class pkgAcquire::Item : public WeakPointable /*{{{*/ /** \brief Represents the process by which a pkgAcquire object should * retrieve a file or a collection of files. diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index 20bf5ae50..3e60423ff 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -44,8 +44,8 @@ using std::string; // SourcesIndex::debSourcesIndex - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ -debSourcesIndex::debSourcesIndex(string URI,string Dist,string Section,bool Trusted) : - pkgIndexFile(Trusted), URI(URI), Dist(Dist), Section(Section) +debSourcesIndex::debSourcesIndex(IndexTarget const &Target,bool const Trusted) : + pkgIndexTargetFile(Target, Trusted) { } /*}}}*/ @@ -56,16 +56,9 @@ debSourcesIndex::debSourcesIndex(string URI,string Dist,string Section,bool Trus string debSourcesIndex::SourceInfo(pkgSrcRecords::Parser const &Record, pkgSrcRecords::File const &File) const { - string Res; - Res = ::URI::ArchiveOnly(URI) + ' '; - if (Dist[Dist.size() - 1] == '/') - { - if (Dist != "/") - Res += Dist; - } - else - Res += Dist + '/' + Section; - + string Res = Target.Description; + Res.erase(Target.Description.rfind(' ')); + Res += " "; Res += Record.Package(); Res += " "; @@ -80,129 +73,19 @@ string debSourcesIndex::SourceInfo(pkgSrcRecords::Parser const &Record, /* */ pkgSrcRecords::Parser *debSourcesIndex::CreateSrcParser() const { - string SourcesURI = _config->FindDir("Dir::State::lists") + - URItoFileName(IndexURI("Sources")); - - std::vector types = APT::Configuration::getCompressionTypes(); - for (std::vector::const_iterator t = types.begin(); t != types.end(); ++t) - { - string p; - p = SourcesURI + '.' + *t; - if (FileExists(p)) - return new debSrcRecordParser(p, this); - } + 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 -{ - string Info = ::URI::ArchiveOnly(URI) + ' '; - if (Dist[Dist.size() - 1] == '/') - { - if (Dist != "/") - Info += Dist; - } - else - Info += Dist + '/' + Section; - Info += " "; - Info += Type; - return Info; -} - /*}}}*/ -// SourcesIndex::Index* - Return the URI to the index files /*{{{*/ -// --------------------------------------------------------------------- -/* */ -string debSourcesIndex::IndexFile(const char *Type) const -{ - string s = URItoFileName(IndexURI(Type)); - - std::vector types = APT::Configuration::getCompressionTypes(); - for (std::vector::const_iterator t = types.begin(); t != types.end(); ++t) - { - string p = s + '.' + *t; - if (FileExists(p)) - return p; - } - return s; -} - -string debSourcesIndex::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 + - "/source/"; - - Res += Type; - return Res; -} - /*}}}*/ -// SourcesIndex::Exists - Check if the index is available /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool debSourcesIndex::Exists() const -{ - return FileExists(IndexFile("Sources")); -} - /*}}}*/ -// SourcesIndex::Size - Return the size of the index /*{{{*/ -// --------------------------------------------------------------------- -/* */ -unsigned long debSourcesIndex::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("Sources"), FileFd::ReadOnly, FileFd::Extension); - if (!f.Failed()) - size = f.Size(); - - 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) +debPackagesIndex::debPackagesIndex(IndexTarget const &Target, bool const Trusted) : + pkgIndexTargetFile(Target, Trusted) { - if (Architecture == "native") - Architecture = _config->Find("APT::Architecture"); } /*}}}*/ // PackagesIndex::ArchiveInfo - Short version of the archive url /*{{{*/ @@ -210,135 +93,40 @@ debPackagesIndex::debPackagesIndex(string const &URI, string const &Dist, string /* This is a shorter version that is designed to be < 60 chars or so */ string debPackagesIndex::ArchiveInfo(pkgCache::VerIterator Ver) const { - string Res = ::URI::ArchiveOnly(URI) + ' '; - if (Dist[Dist.size() - 1] == '/') - { - if (Dist != "/") - Res += Dist; - } - else - Res += Dist + '/' + Section; - + std::string const Dist = Target.Option("RELEASE"); + string Res = Target.Option("SITE") + " " + Dist; + std::string const Component = Target.Option("COMPONENT"); + if (Component.empty() == false) + Res += "/" + Component; + Res += " "; Res += Ver.ParentPkg().Name(); Res += " "; - if (Dist[Dist.size() - 1] != '/') + 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 -{ - string Info = ::URI::ArchiveOnly(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 types = APT::Configuration::getCompressionTypes(); - for (std::vector::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"); + string const PackageFile = IndexFileName(); FileFd Pkg(PackageFile,FileFd::ReadOnly, FileFd::Extension); - debListParser Parser(&Pkg, Architecture); + debListParser Parser(&Pkg, Target.Option("ARCHITECTURE")); if (_error->PendingError() == true) return _error->Error("Problem opening %s",PackageFile.c_str()); if (Prog != NULL) - Prog->SubProgress(0,Info("Packages")); + Prog->SubProgress(0, Target.Description); + + + std::string const URI = Target.Option("REPO_URI"); + std::string Dist = Target.Option("RELEASE"); + if (Dist.empty()) + Dist = "/"; ::URI Tmp(URI); if (Gen.SelectFile(PackageFile,Tmp.Host,*this) == false) return _error->Error("Problem with SelectFile %s",PackageFile.c_str()); @@ -370,7 +158,7 @@ bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const if (_error->PendingError() == true) return false; - Parser.LoadReleaseInfo(File,Rel,Section); + Parser.LoadReleaseInfo(File, Rel, Target.Option("COMPONENT")); } return true; @@ -381,7 +169,7 @@ bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const /* */ pkgCache::PkgFileIterator debPackagesIndex::FindInCache(pkgCache &Cache) const { - string FileName = IndexFile("Packages"); + string const FileName = IndexFileName(); pkgCache::PkgFileIterator File = Cache.FileBegin(); for (; File.end() == false; ++File) { @@ -411,113 +199,13 @@ pkgCache::PkgFileIterator debPackagesIndex::FindInCache(pkgCache &Cache) const /*}}}*/ // 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) +debTranslationsIndex::debTranslationsIndex(IndexTarget const &Target) : + pkgIndexTargetFile(Target, true) {} /*}}}*/ -// TranslationIndex::Trans* - Return the URI to the translation files /*{{{*/ -// --------------------------------------------------------------------- -/* */ -string debTranslationsIndex::IndexFile(const char *Type) const -{ - string s =_config->FindDir("Dir::State::lists") + URItoFileName(IndexURI(Type)); - - std::vector types = APT::Configuration::getCompressionTypes(); - for (std::vector::const_iterator t = types.begin(); t != types.end(); ++t) - { - string p = s + '.' + *t; - if (FileExists(p)) - return p; - } - return s; -} -string debTranslationsIndex::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 + - "/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::ArchiveOnly(URI) + ' '; - if (Dist[Dist.size() - 1] == '/') - { - if (Dist != "/") - Info += Dist; - } - else - Info += Dist + '/' + Section; - Info += " "; - Info += Type; - return Info; -} - /*}}}*/ bool debTranslationsIndex::HasPackages() const /*{{{*/ { - return FileExists(IndexFile(Language.c_str())); -} - /*}}}*/ -// TranslationsIndex::Exists - Check if the index is available /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool debTranslationsIndex::Exists() const -{ - return FileExists(IndexFile(Language.c_str())); -} - /*}}}*/ -// TranslationsIndex::Size - Return the size of the index /*{{{*/ -// --------------------------------------------------------------------- -/* This is really only used for progress reporting. */ -unsigned long debTranslationsIndex::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(Language.c_str()), FileFd::ReadOnly, FileFd::Extension); - if (!f.Failed()) - size = f.Size(); - - if (_error->PendingError() == true) - size = 0; - _error->RevertToStack(); - - return size; + return Exists(); } /*}}}*/ // TranslationsIndex::Merge - Load the index file into a cache /*{{{*/ @@ -526,7 +214,7 @@ unsigned long debTranslationsIndex::Size() const bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const { // Check the translation file, if in use - string TranslationFile = IndexFile(Language.c_str()); + string const TranslationFile = IndexFileName(); if (FileExists(TranslationFile)) { FileFd Trans(TranslationFile,FileFd::ReadOnly, FileFd::Extension); @@ -535,7 +223,7 @@ bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const return false; if (Prog != NULL) - Prog->SubProgress(0, Info(TranslationFile.c_str())); + Prog->SubProgress(0, Target.Description); if (Gen.SelectFile(TranslationFile,string(),*this) == false) return _error->Error("Problem with SelectFile %s",TranslationFile.c_str()); @@ -556,8 +244,8 @@ bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const /* */ pkgCache::PkgFileIterator debTranslationsIndex::FindInCache(pkgCache &Cache) const { - string FileName = IndexFile(Language.c_str()); - + string FileName = IndexFileName(); + pkgCache::PkgFileIterator File = Cache.FileBegin(); for (; File.end() == false; ++File) { @@ -580,10 +268,11 @@ pkgCache::PkgFileIterator debTranslationsIndex::FindInCache(pkgCache &Cache) con return pkgCache::PkgFileIterator(Cache); } return File; - } + } return File; } /*}}}*/ + // StatusIndex::debStatusIndex - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ diff --git a/apt-pkg/deb/debindexfile.h b/apt-pkg/deb/debindexfile.h index 1e5882071..dd3f212b2 100644 --- a/apt-pkg/deb/debindexfile.h +++ b/apt-pkg/deb/debindexfile.h @@ -30,19 +30,16 @@ class pkgCacheGenerator; class APT_HIDDEN debStatusIndex : public pkgIndexFile { - /** \brief dpointer placeholder (for later in case we need it) */ - void *d; - protected: std::string File; public: 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;}; @@ -54,91 +51,42 @@ class APT_HIDDEN debStatusIndex : public pkgIndexFile debStatusIndex(std::string 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 APT_HIDDEN debPackagesIndex : public pkgIndexTargetFile +{ public: - + virtual const Type *GetType() const 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; - + // 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"); + debPackagesIndex(IndexTarget const &Target, bool const Trusted); virtual ~debPackagesIndex(); }; -class APT_HIDDEN debTranslationsIndex : public pkgIndexFile +class APT_HIDDEN debTranslationsIndex : public pkgIndexTargetFile { - /** \brief dpointer placeholder (for later in case we need it) */ - void *d; - - std::string const URI; - std::string const Dist; - std::string const Section; - std::string const Language; - - 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; - // 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; - 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 APT_HIDDEN debSourcesIndex : public pkgIndexTargetFile { - /** \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; - public: virtual const Type *GetType() const APT_CONST; @@ -146,20 +94,14 @@ class APT_HIDDEN debSourcesIndex : public pkgIndexFile // 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; // Interface for the record parsers virtual pkgSrcRecords::Parser *CreateSrcParser() const; - + // 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); + + debSourcesIndex(IndexTarget const &Target, bool const Trusted); virtual ~debSourcesIndex(); }; diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index d4e340be0..9108a5097 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -140,6 +140,7 @@ void foreachTarget(std::string const URI, std::string const Dist, Options.insert(std::make_pair("LANGUAGE", *l)); Options.insert(std::make_pair("ARCHITECTURE", "source")); Options.insert(std::make_pair("BASE_URI", baseURI)); + Options.insert(std::make_pair("REPO_URI", URI)); Options.insert(std::make_pair("CREATED_BY", *T)); Call(MetaKey, ShortDesc, LongDesc, IsOptional, Options); @@ -186,6 +187,7 @@ void foreachTarget(std::string const URI, std::string const Dist, Options.insert(std::make_pair("LANGUAGE", *l)); Options.insert(std::make_pair("ARCHITECTURE", a->first)); Options.insert(std::make_pair("BASE_URI", baseURI)); + Options.insert(std::make_pair("REPO_URI", URI)); Options.insert(std::make_pair("CREATED_BY", *T)); Call(MetaKey, ShortDesc, LongDesc, IsOptional, Options); @@ -294,55 +296,25 @@ bool debReleaseIndex::IsTrusted() const return FileExists(VerifiedSigFile); } -struct GetIndexFilesClass +std::vector *debReleaseIndex::GetIndexFiles() { - vector * const Indexes; - std::string const URI; - std::string const Release; - bool const IsTrusted; + if (Indexes != NULL) + return Indexes; - void operator()(std::string const &/*URI*/, std::string const &/*ShortDesc*/, std::string const &/*LongDesc*/, - bool const /*IsOptional*/, std::map Options) + Indexes = new std::vector(); + std::vector const Targets = GetIndexTargets(); + bool const istrusted = IsTrusted(); + for (std::vector::const_iterator T = Targets.begin(); T != Targets.end(); ++T) { - std::string const TargetName = Options.find("CREATED_BY")->second; + std::string const TargetName = T->Options.find("CREATED_BY")->second; if (TargetName == "Packages") - { - Indexes->push_back(new debPackagesIndex( - URI, - Release, - Options.find("COMPONENT")->second, - IsTrusted, - Options.find("ARCHITECTURE")->second - )); - } + Indexes->push_back(new debPackagesIndex(*T, istrusted)); else if (TargetName == "Sources") - Indexes->push_back(new debSourcesIndex( - URI, - Release, - Options.find("COMPONENT")->second, - IsTrusted - )); + Indexes->push_back(new debSourcesIndex(*T, istrusted)); else if (TargetName == "Translations") - Indexes->push_back(new debTranslationsIndex( - URI, - Release, - Options.find("COMPONENT")->second, - Options.find("LANGUAGE")->second - )); + Indexes->push_back(new debTranslationsIndex(*T)); } - - GetIndexFilesClass(std::string const &URI, std::string const &Release, bool const IsTrusted) : - Indexes(new vector ), URI(URI), Release(Release), IsTrusted(IsTrusted) {} -}; - -std::vector *debReleaseIndex::GetIndexFiles() -{ - if (Indexes != NULL) - return Indexes; - - GetIndexFilesClass comp(URI, Dist, IsTrusted()); - foreachTarget(URI, Dist, ArchEntries, comp); - return Indexes = comp.Indexes; + return Indexes; } void debReleaseIndex::PushSectionEntry(vector const &Archs, const debSectionEntry *Entry) { diff --git a/apt-pkg/indexfile.cc b/apt-pkg/indexfile.cc index 89615cb41..bbcd9246c 100644 --- a/apt-pkg/indexfile.cc +++ b/apt-pkg/indexfile.cc @@ -10,8 +10,10 @@ // Include Files /*{{{*/ #include +#include #include #include +#include #include #include #include @@ -48,27 +50,26 @@ pkgIndexFile::Type *pkgIndexFile::Type::GetType(const char *Type) if (strcmp(GlobalList[I]->Label,Type) == 0) return GlobalList[I]; return 0; +} + /*}}}*/ +pkgIndexFile::pkgIndexFile(bool Trusted) : /*{{{*/ + Trusted(Trusted) +{ } /*}}}*/ // IndexFile::ArchiveInfo - Stub /*{{{*/ -// --------------------------------------------------------------------- -/* */ std::string pkgIndexFile::ArchiveInfo(pkgCache::VerIterator /*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 { @@ -110,3 +111,77 @@ 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, + std::map const &Options) : + URI(URI), Description(LongDesc), ShortDesc(ShortDesc), MetaKey(MetaKey), IsOptional(IsOptional), Options(Options) +{ +} + /*}}}*/ +std::string IndexTarget::Option(std::string const &Key) const /*{{{*/ +{ + std::map::const_iterator const M = Options.find(Key); + if (M == Options.end()) + return ""; + return M->second; +} + /*}}}*/ + +pkgIndexTargetFile::pkgIndexTargetFile(IndexTarget const &Target, bool const Trusted) :/*{{{*/ + pkgIndexFile(Trusted), Target(Target) +{ +} + /*}}}*/ +std::string pkgIndexTargetFile::ArchiveURI(std::string File) const/*{{{*/ +{ + return Target.Option("REPO_URI") + File; +} + /*}}}*/ +std::string pkgIndexTargetFile::Describe(bool Short) const /*{{{*/ +{ + if (Short) + return Target.Description; + return Target.Description + " (" + IndexFileName() + ")"; +} + /*}}}*/ +std::string pkgIndexTargetFile::IndexFileName() const /*{{{*/ +{ + std::string const s =_config->FindDir("Dir::State::lists") + URItoFileName(Target.URI); + if (FileExists(s)) + return s; + + std::vector types = APT::Configuration::getCompressionTypes(); + for (std::vector::const_iterator t = types.begin(); t != types.end(); ++t) + { + std::string p = s + '.' + *t; + if (FileExists(p)) + return p; + } + return s; +} + /*}}}*/ +unsigned long pkgIndexTargetFile::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 pkgIndexTargetFile::Exists() const /*{{{*/ +{ + return FileExists(IndexFileName()); +} + /*}}}*/ diff --git a/apt-pkg/indexfile.h b/apt-pkg/indexfile.h index 817165f08..e6e429c2c 100644 --- a/apt-pkg/indexfile.h +++ b/apt-pkg/indexfile.h @@ -28,6 +28,7 @@ #include #include +#include #include #ifndef APT_8_CLEANER_HEADERS @@ -40,17 +41,48 @@ class pkgAcquire; class pkgCacheGenerator; 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 Target specific options defined by the implementation */ + std::map Options; + + IndexTarget(std::string const &MetaKey, std::string const &ShortDesc, + std::string const &LongDesc, std::string const &URI, bool const IsOptional, + std::map const &Options); + + std::string Option(std::string const &Key) const; +}; + /*}}}*/ + class pkgIndexFile { protected: bool Trusted; - + public: class Type { public: - + // Global list of Items supported static Type **GlobalList; static unsigned long GlobalListLen; @@ -70,7 +102,7 @@ class pkgIndexFile virtual std::string ArchiveInfo(pkgCache::VerIterator 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 Short = false) const = 0; // Interface for acquire virtual std::string ArchiveURI(std::string /*File*/) const {return std::string();}; @@ -95,9 +127,25 @@ class pkgIndexFile static std::string LanguageCode(); bool IsTrusted() const { return Trusted; }; - - pkgIndexFile(bool Trusted): Trusted(Trusted) {}; + + pkgIndexFile(bool Trusted); virtual ~pkgIndexFile() {}; }; +class pkgIndexTargetFile : public pkgIndexFile +{ +protected: + IndexTarget const Target; + + std::string IndexFileName() const; + +public: + virtual std::string ArchiveURI(std::string File) const; + virtual std::string Describe(bool Short = false) const; + virtual bool Exists() const; + virtual unsigned long Size() const; + + pkgIndexTargetFile(IndexTarget const &Target, bool const Trusted); +}; + #endif -- cgit v1.2.3 From 001c76fe204e17916a6c8b351ff30b67d32cb779 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 11 Jun 2015 11:59:16 +0200 Subject: use an enum instead of strings as IndexTarget::Option interface Strings are easy to typo and we can keep the extensibility we require here with a simple enum we can append to without endangering ABI. Git-Dch: Ignore --- apt-pkg/deb/debindexfile.cc | 14 +++++++------- apt-pkg/deb/debmetaindex.cc | 2 +- apt-pkg/indexfile.cc | 18 ++++++++++++++++-- apt-pkg/indexfile.h | 16 ++++++++++++++-- 4 files changed, 38 insertions(+), 12 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index 3e60423ff..7aad65c0e 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -93,9 +93,9 @@ debPackagesIndex::debPackagesIndex(IndexTarget const &Target, bool const Trusted /* This is a shorter version that is designed to be < 60 chars or so */ string debPackagesIndex::ArchiveInfo(pkgCache::VerIterator Ver) const { - std::string const Dist = Target.Option("RELEASE"); - string Res = Target.Option("SITE") + " " + Dist; - std::string const Component = Target.Option("COMPONENT"); + std::string const Dist = Target.Option(IndexTarget::RELEASE); + string Res = Target.Option(IndexTarget::SITE) + " " + Dist; + std::string const Component = Target.Option(IndexTarget::COMPONENT); if (Component.empty() == false) Res += "/" + Component; @@ -115,7 +115,7 @@ bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const { string const PackageFile = IndexFileName(); FileFd Pkg(PackageFile,FileFd::ReadOnly, FileFd::Extension); - debListParser Parser(&Pkg, Target.Option("ARCHITECTURE")); + debListParser Parser(&Pkg, Target.Option(IndexTarget::ARCHITECTURE)); if (_error->PendingError() == true) return _error->Error("Problem opening %s",PackageFile.c_str()); @@ -123,8 +123,8 @@ bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const Prog->SubProgress(0, Target.Description); - std::string const URI = Target.Option("REPO_URI"); - std::string Dist = Target.Option("RELEASE"); + std::string const URI = Target.Option(IndexTarget::REPO_URI); + std::string Dist = Target.Option(IndexTarget::RELEASE); if (Dist.empty()) Dist = "/"; ::URI Tmp(URI); @@ -158,7 +158,7 @@ bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const if (_error->PendingError() == true) return false; - Parser.LoadReleaseInfo(File, Rel, Target.Option("COMPONENT")); + Parser.LoadReleaseInfo(File, Rel, Target.Option(IndexTarget::COMPONENT)); } return true; diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 9108a5097..c05e7cdae 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -306,7 +306,7 @@ std::vector *debReleaseIndex::GetIndexFiles() bool const istrusted = IsTrusted(); for (std::vector::const_iterator T = Targets.begin(); T != Targets.end(); ++T) { - std::string const TargetName = T->Options.find("CREATED_BY")->second; + std::string const TargetName = T->Option(IndexTarget::CREATED_BY); if (TargetName == "Packages") Indexes->push_back(new debPackagesIndex(*T, istrusted)); else if (TargetName == "Sources") diff --git a/apt-pkg/indexfile.cc b/apt-pkg/indexfile.cc index bbcd9246c..72d35ddcc 100644 --- a/apt-pkg/indexfile.cc +++ b/apt-pkg/indexfile.cc @@ -120,8 +120,22 @@ IndexTarget::IndexTarget(std::string const &MetaKey, std::string const &ShortDes { } /*}}}*/ -std::string IndexTarget::Option(std::string const &Key) const /*{{{*/ +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(CREATED_BY); +#undef APT_CASE + } std::map::const_iterator const M = Options.find(Key); if (M == Options.end()) return ""; @@ -136,7 +150,7 @@ pkgIndexTargetFile::pkgIndexTargetFile(IndexTarget const &Target, bool const Tru /*}}}*/ std::string pkgIndexTargetFile::ArchiveURI(std::string File) const/*{{{*/ { - return Target.Option("REPO_URI") + File; + return Target.Option(IndexTarget::REPO_URI) + File; } /*}}}*/ std::string pkgIndexTargetFile::Describe(bool Short) const /*{{{*/ diff --git a/apt-pkg/indexfile.h b/apt-pkg/indexfile.h index e6e429c2c..c38cf0bf0 100644 --- a/apt-pkg/indexfile.h +++ b/apt-pkg/indexfile.h @@ -61,14 +61,26 @@ class IndexTarget /*{{{*/ /** \brief Is it okay if the file isn't found in the meta index */ bool IsOptional; - /** \brief Target specific options defined by the implementation */ + /** \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 Options; IndexTarget(std::string const &MetaKey, std::string const &ShortDesc, std::string const &LongDesc, std::string const &URI, bool const IsOptional, std::map const &Options); - std::string Option(std::string const &Key) const; + enum OptionKeys { + SITE, + RELEASE, + COMPONENT, + LANGUAGE, + ARCHITECTURE, + BASE_URI, + REPO_URI, + CREATED_BY, + }; + std::string Option(OptionKeys const Key) const; }; /*}}}*/ -- cgit v1.2.3 From 8881b11eacd735148d087c8c0f53827cb537b582 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 11 Jun 2015 16:40:45 +0200 Subject: implement 'apt-get files' to access index targets Downloading additional files is only half the job. We still need a way to allow external tools to know where the files are they requested for download given that we don't want them to choose their own location. 'apt-get files' is our answer to this showing by default in a deb822 format information about each IndexTarget with the potential to filter the records based on lines and an option to change the output format. The command serves also as an example on how to get to this information via libapt. --- apt-pkg/deb/debmetaindex.cc | 17 ++++++++++++----- apt-pkg/indexfile.cc | 18 +++++++++++++++++- apt-pkg/indexfile.h | 3 +++ 3 files changed, 32 insertions(+), 6 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index c05e7cdae..8e4c2be2d 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -136,11 +136,14 @@ void foreachTarget(std::string const URI, std::string const Dist, std::map Options; Options.insert(std::make_pair("SITE", Site)); Options.insert(std::make_pair("RELEASE", Release)); - Options.insert(std::make_pair("COMPONENT", (*I)->Section)); - Options.insert(std::make_pair("LANGUAGE", *l)); + if (MetaKey.find("$(COMPONENT)") != std::string::npos) + Options.insert(std::make_pair("COMPONENT", (*I)->Section)); + if (MetaKey.find("$(LANGUAGE)") != std::string::npos) + Options.insert(std::make_pair("LANGUAGE", *l)); Options.insert(std::make_pair("ARCHITECTURE", "source")); 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)); Call(MetaKey, ShortDesc, LongDesc, IsOptional, Options); @@ -183,11 +186,15 @@ void foreachTarget(std::string const URI, std::string const Dist, std::map Options; Options.insert(std::make_pair("SITE", Site)); Options.insert(std::make_pair("RELEASE", Release)); - Options.insert(std::make_pair("COMPONENT", (*I)->Section)); - Options.insert(std::make_pair("LANGUAGE", *l)); - Options.insert(std::make_pair("ARCHITECTURE", a->first)); + if (MetaKey.find("$(COMPONENT)") != std::string::npos) + Options.insert(std::make_pair("COMPONENT", (*I)->Section)); + if (MetaKey.find("$(LANGUAGE)") != std::string::npos) + Options.insert(std::make_pair("LANGUAGE", *l)); + if (MetaKey.find("$(ARCHITECTURE)") != std::string::npos) + Options.insert(std::make_pair("ARCHITECTURE", a->first)); Options.insert(std::make_pair("BASE_URI", baseURI)); Options.insert(std::make_pair("REPO_URI", URI)); + Options.insert(std::make_pair("TARGET_OF", "deb")); Options.insert(std::make_pair("CREATED_BY", *T)); Call(MetaKey, ShortDesc, LongDesc, IsOptional, Options); diff --git a/apt-pkg/indexfile.cc b/apt-pkg/indexfile.cc index 72d35ddcc..33fb48e35 100644 --- a/apt-pkg/indexfile.cc +++ b/apt-pkg/indexfile.cc @@ -133,8 +133,10 @@ std::string IndexTarget::Option(OptionKeys const EnumKey) const /*{{{*/ 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); } std::map::const_iterator const M = Options.find(Key); if (M == Options.end()) @@ -142,6 +144,20 @@ std::string IndexTarget::Option(OptionKeys const EnumKey) const /*{{{*/ return M->second; } /*}}}*/ +std::string IndexTarget::Format(std::string format) const /*{{{*/ +{ + for (std::map::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; +} + /*}}}*/ pkgIndexTargetFile::pkgIndexTargetFile(IndexTarget const &Target, bool const Trusted) :/*{{{*/ pkgIndexFile(Trusted), Target(Target) @@ -162,7 +178,7 @@ std::string pkgIndexTargetFile::Describe(bool Short) const /*{{{*/ /*}}}*/ std::string pkgIndexTargetFile::IndexFileName() const /*{{{*/ { - std::string const s =_config->FindDir("Dir::State::lists") + URItoFileName(Target.URI); + std::string const s = Target.Option(IndexTarget::FILENAME); if (FileExists(s)) return s; diff --git a/apt-pkg/indexfile.h b/apt-pkg/indexfile.h index c38cf0bf0..220c415ac 100644 --- a/apt-pkg/indexfile.h +++ b/apt-pkg/indexfile.h @@ -79,8 +79,11 @@ class IndexTarget /*{{{*/ BASE_URI, REPO_URI, CREATED_BY, + TARGET_OF, + FILENAME, }; std::string Option(OptionKeys const Key) const; + std::string Format(std::string format) const; }; /*}}}*/ -- cgit v1.2.3 From b07aeb1a6e24825e534167a737043441e871de9f Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 12 Jun 2015 02:08:53 +0200 Subject: store Release files data in the Cache We used to read the Release file for each Packages file and store the data in the PackageFile struct even through potentially many Packages (and Translation-*) files could use the same data. The point of the exercise isn't the duplicated data through. Having the Release files as first-class citizens in the Cache allows us to properly track their state as well as allows us to use the information also for files which aren't in the cache, but where we know to which Release file they belong (Sources are an example for this). This modifies the pkgCache structs, especially the PackagesFile struct which depending on how libapt users access the data in these structs can mean huge breakage or no visible change. As a single data point: aptitude seems to be fine with this. Even if there is breakage it is trivial to fix in a backportable way while avoiding breakage for everyone would be a huge pain for us. Note that not all PackageFile structs have a corresponding ReleaseFile. In particular the dpkg/status file as well as *.deb files have not. As these have only a Archive property need, the Component property takes over this duty and the ReleaseFile remains zero. This is also the reason why it isn't needed nor particularily recommended to change from PackagesFile to ReleaseFile blindly. Sticking with the earlier is usually the better option. --- apt-pkg/acquire-item.cc | 6 +- apt-pkg/cacheiterators.h | 46 +++++++-- apt-pkg/clean.cc | 2 +- apt-pkg/deb/debindexfile.cc | 42 ++------ apt-pkg/deb/debindexfile.h | 1 - apt-pkg/deb/deblistparser.cc | 37 ------- apt-pkg/deb/deblistparser.h | 6 +- apt-pkg/deb/debmetaindex.cc | 124 +++++++++++++++++++++- apt-pkg/deb/debmetaindex.h | 6 ++ apt-pkg/deb/dpkgpm.cc | 4 +- apt-pkg/depcache.cc | 6 +- apt-pkg/edsp.cc | 2 +- apt-pkg/edsp/edspindexfile.cc | 5 +- apt-pkg/edsp/edsplistparser.cc | 4 +- apt-pkg/edsp/edsplistparser.h | 4 +- apt-pkg/metaindex.cc | 17 ++++ apt-pkg/metaindex.h | 6 ++ apt-pkg/pkgcache.cc | 77 ++++++++++---- apt-pkg/pkgcache.h | 75 +++++++++++--- apt-pkg/pkgcachegen.cc | 226 ++++++++++++++++++++++++++++++++--------- apt-pkg/pkgcachegen.h | 10 +- apt-pkg/policy.cc | 15 ++- apt-pkg/versionmatch.cc | 45 ++++---- apt-pkg/versionmatch.h | 4 +- 24 files changed, 556 insertions(+), 214 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index d4191f00e..d6e9ccbe0 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -2568,7 +2568,7 @@ pkgAcqArchive::pkgAcqArchive(pkgAcquire * const Owner,pkgSourceList * const Sour // 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; } @@ -2636,14 +2636,14 @@ bool pkgAcqArchive::QueueNext() { pkgCache::PkgFileIterator const PkgF = Vf.File(); // Ignore not source sources - if ((PkgF->Flags & pkgCache::Flag::NotSource) != 0) + if (PkgF.Flagged(pkgCache::Flag::NotSource)) continue; // Try to cross match against the source list pkgIndexFile *Index; if (Sources->FindIndex(PkgF, Index) == false) continue; - LocalSource = (PkgF->Flags & pkgCache::Flag::LocalSource) == pkgCache::Flag::LocalSource; + LocalSource = PkgF.Flagged(pkgCache::Flag::LocalSource); // only try to get a trusted package from another source if that source // is also trusted diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h index fe798799c..301da6fc4 100644 --- a/apt-pkg/cacheiterators.h +++ b/apt-pkg/cacheiterators.h @@ -367,27 +367,61 @@ class pkgCache::PrvIterator : public Iterator { } }; /*}}}*/ -// Package file /*{{{*/ -class pkgCache::PkgFileIterator : public Iterator { +// Release file /*{{{*/ +class pkgCache::RlsFileIterator : public Iterator { protected: - inline PackageFile* OwnerPointer() const { - return (Owner != 0) ? Owner->PkgFileP : 0; + inline ReleaseFile* OwnerPointer() const { + return (Owner != 0) ? Owner->RlsFileP : 0; } public: // Iteration - void operator ++(int) {if (S != Owner->PkgFileP) S = Owner->PkgFileP + S->NextFile;} + void operator ++(int) {if (S != Owner->RlsFileP) S = Owner->RlsFileP + S->NextFile;} inline void operator ++() {operator ++(0);} // 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() {} + inline RlsFileIterator(pkgCache &Owner) : Iterator(Owner, Owner.RlsFileP) {} + inline RlsFileIterator(pkgCache &Owner,ReleaseFile *Trg) : Iterator(Owner, Trg) {} +}; + /*}}}*/ +// Package file /*{{{*/ +class pkgCache::PkgFileIterator : public Iterator { + protected: + inline PackageFile* OwnerPointer() const { + return (Owner != 0) ? Owner->PkgFileP : 0; + } + + public: + // Iteration + void operator ++(int) {if (S != Owner->PkgFileP) S = Owner->PkgFileP + S->NextFile;} + inline void operator ++() {operator ++(0);} + + // 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;} diff --git a/apt-pkg/clean.cc b/apt-pkg/clean.cc index 6edce5b6d..0fca60ba9 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; diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index 7aad65c0e..3a79cbc58 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -128,7 +128,7 @@ bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const if (Dist.empty()) Dist = "/"; ::URI Tmp(URI); - if (Gen.SelectFile(PackageFile,Tmp.Host,*this) == false) + if (Gen.SelectFile(PackageFile, *this, Target.Option(IndexTarget::COMPONENT)) == false) return _error->Error("Problem with SelectFile %s",PackageFile.c_str()); // Store the IMS information @@ -136,31 +136,10 @@ bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const pkgCacheGenerator::Dynamic 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, Target.Option(IndexTarget::COMPONENT)); - } - return true; } /*}}}*/ @@ -221,17 +200,17 @@ bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const debTranslationsParser TransParser(&Trans); if (_error->PendingError() == true) return false; - + if (Prog != NULL) Prog->SubProgress(0, Target.Description); - if (Gen.SelectFile(TranslationFile,string(),*this) == false) + if (Gen.SelectFile(TranslationFile, *this, Target.Option(IndexTarget::COMPONENT), pkgCache::Flag::NotSource) == 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()); } @@ -305,18 +284,17 @@ bool debStatusIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const if (Prog != NULL) Prog->SubProgress(0,File); - if (Gen.SelectFile(File,string(),*this,pkgCache::Flag::NotSource) == false) + if (Gen.SelectFile(File, *this, "now", pkgCache::Flag::NotSource) == false) return _error->Error("Problem with SelectFile %s",File.c_str()); // Store the IMS information pkgCache::PkgFileIterator CFile = Gen.GetCurFile(); + pkgCacheGenerator::Dynamic DynFile(CFile); 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 _error->Error("Problem with MergeList %s",File.c_str()); return true; } /*}}}*/ @@ -431,7 +409,7 @@ bool debDebPkgFileIndex::Merge(pkgCacheGenerator& Gen, OpProgress* Prog) const // and give it to the list parser debDebFileParser Parser(DebControl, DebFile); - if(Gen.SelectFile(DebFile, "local", *this, pkgCache::Flag::LocalSource) == false) + if(Gen.SelectFile(DebFile, *this, "now", pkgCache::Flag::LocalSource) == false) return _error->Error("Problem with SelectFile %s", DebFile.c_str()); pkgCache::PkgFileIterator File = Gen.GetCurFile(); diff --git a/apt-pkg/deb/debindexfile.h b/apt-pkg/deb/debindexfile.h index dd3f212b2..6b8c78e5a 100644 --- a/apt-pkg/deb/debindexfile.h +++ b/apt-pkg/deb/debindexfile.h @@ -45,7 +45,6 @@ class APT_HIDDEN debStatusIndex : public pkgIndexFile 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); diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index b80b57bc4..c5e77b0ff 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -951,43 +951,6 @@ bool debListParser::Step() 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(); -} - /*}}}*/ // ListParser::GetPrio - Convert the priority from a string /*{{{*/ // --------------------------------------------------------------------- /* */ diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h index 6279d8399..420d5ff08 100644 --- a/apt-pkg/deb/deblistparser.h +++ b/apt-pkg/deb/deblistparser.h @@ -80,9 +80,9 @@ class APT_HIDDEN debListParser : public pkgCacheGenerator::ListParser virtual map_filesize_t Size() {return Section.size();}; virtual bool Step(); - - bool LoadReleaseInfo(pkgCache::PkgFileIterator &FileI,FileFd &File, - std::string section); + + 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); diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 8e4c2be2d..994b95849 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -1,5 +1,6 @@ #include +#include #include #include #include @@ -10,10 +11,12 @@ #include #include #include -#include #include +#include +#include +#include +#include -#include #include #include #include @@ -21,6 +24,11 @@ #include #include +#include +#include +#include +#include + using namespace std; string debReleaseIndex::MetaIndexInfo(const char *Type) const @@ -37,6 +45,10 @@ 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 { @@ -339,6 +351,114 @@ debReleaseIndex::debSectionEntry::debSectionEntry (string const &Section, bool const &IsSrc): Section(Section), IsSrc(IsSrc) {} +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); + + ::URI Tmp(URI); + if (Gen.SelectReleaseFile(ReleaseFile, Tmp.Host) == false) + return _error->Error("Problem with SelectReleaseFile %s", ReleaseFile.c_str()); + + if (releaseExists == false) + return 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; + + // Store the IMS information + pkgCache::RlsFileIterator File = Gen.GetCurRlsFile(); + pkgCacheGenerator::Dynamic 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) const +{ + std::string ReleaseFile; + bool const releaseExists = ReleaseFileName(this, ReleaseFile); + + pkgCache::RlsFileIterator File = Cache.RlsFileBegin(); + for (; File.end() == false; ++File) + { + if (File->FileName == 0 || ReleaseFile != File.FileName()) + continue; + + // empty means the file does not exist by "design" + if (releaseExists == false && File->Size == 0) + return File; + + struct stat St; + if (stat(File.FileName(),&St) != 0) + { + if (_config->FindB("Debug::pkgCacheGen", false)) + std::clog << "ReleaseIndex::FindInCache - stat failed on " << File.FileName() << std::endl; + return pkgCache::RlsFileIterator(Cache); + } + if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime) + { + 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; + } + + return File; +} + /*}}}*/ + class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type { protected: diff --git a/apt-pkg/deb/debmetaindex.h b/apt-pkg/deb/debmetaindex.h index 0b1b08432..7e9942710 100644 --- a/apt-pkg/deb/debmetaindex.h +++ b/apt-pkg/deb/debmetaindex.h @@ -20,6 +20,8 @@ class pkgAcquire; class pkgIndexFile; class debDebPkgFileIndex; class IndexTarget; +class pkgCacheGenerator; +class OpProgress; class APT_HIDDEN debReleaseIndex : public metaIndex { public: @@ -48,6 +50,10 @@ class APT_HIDDEN debReleaseIndex : public metaIndex { virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false) const; virtual std::vector GetIndexTargets() const; + virtual std::string Describe() const; + virtual pkgCache::RlsFileIterator FindInCache(pkgCache &Cache) const; + virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const; + std::string MetaIndexInfo(const char *Type) const; std::string MetaIndexFile(const char *Types) const; std::string MetaIndexURI(const char *Type) const; diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index a7a66c75d..6ee939edd 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -205,8 +205,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; } /*}}}*/ diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index b73c336db..36e1ac9ec 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -1685,13 +1685,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; diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index 3c6a7e30f..41cc2cdfe 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -129,7 +129,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); diff --git a/apt-pkg/edsp/edspindexfile.cc b/apt-pkg/edsp/edspindexfile.cc index d00536362..43dd44a79 100644 --- a/apt-pkg/edsp/edspindexfile.cc +++ b/apt-pkg/edsp/edspindexfile.cc @@ -49,15 +49,14 @@ bool edspIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const if (Prog != NULL) Prog->SubProgress(0,File); - if (Gen.SelectFile(File,std::string(),*this) == false) + if (Gen.SelectFile(File, *this, "edsp") == false) return _error->Error("Problem with SelectFile %s",File.c_str()); // Store the IMS information pkgCache::PkgFileIterator CFile = Gen.GetCurFile(); + pkgCacheGenerator::Dynamic DynFile(CFile); 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()); diff --git a/apt-pkg/edsp/edsplistparser.cc b/apt-pkg/edsp/edsplistparser.cc index 212dc7840..d62abe709 100644 --- a/apt-pkg/edsp/edsplistparser.cc +++ b/apt-pkg/edsp/edsplistparser.cc @@ -86,8 +86,8 @@ 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; } diff --git a/apt-pkg/edsp/edsplistparser.h b/apt-pkg/edsp/edsplistparser.h index 86cd77606..abe2ef139 100644 --- a/apt-pkg/edsp/edsplistparser.h +++ b/apt-pkg/edsp/edsplistparser.h @@ -34,8 +34,8 @@ class APT_HIDDEN edspListParser : public debListParser virtual MD5SumValue Description_md5(); virtual unsigned short VersionHash(); - 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 = ""); diff --git a/apt-pkg/metaindex.cc b/apt-pkg/metaindex.cc index 31a8ec009..35ab6c53b 100644 --- a/apt-pkg/metaindex.cc +++ b/apt-pkg/metaindex.cc @@ -1,4 +1,5 @@ // Include Files /*{{{*/ +#include #include #include @@ -22,6 +23,22 @@ std::string metaIndex::LocalFileName() const } #endif +std::string metaIndex::Describe() const +{ + return "Release"; +} + +pkgCache::RlsFileIterator metaIndex::FindInCache(pkgCache &Cache) const +{ + return pkgCache::RlsFileIterator(Cache); +} + +bool metaIndex::Merge(pkgCacheGenerator &Gen,OpProgress *) const +{ + return Gen.SelectReleaseFile("", ""); +} + + metaIndex::metaIndex(std::string const &URI, std::string const &Dist, char const * const Type) : Indexes(NULL), Type(Type), URI(URI), Dist(Dist), Trusted(false) diff --git a/apt-pkg/metaindex.h b/apt-pkg/metaindex.h index 4e5de8be0..20c879a89 100644 --- a/apt-pkg/metaindex.h +++ b/apt-pkg/metaindex.h @@ -23,6 +23,8 @@ using std::string; class pkgAcquire; class IndexTarget; +class pkgCacheGenerator; +class OpProgress; class metaIndex { @@ -51,6 +53,10 @@ class metaIndex virtual std::vector *GetIndexFiles() = 0; virtual bool IsTrusted() const = 0; + virtual std::string Describe() const; + virtual pkgCache::RlsFileIterator FindInCache(pkgCache &Cache) const; + virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const; + metaIndex(std::string const &URI, std::string const &Dist, char const * const Type); virtual ~metaIndex(); diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index 864ae0f60..9fe382108 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -61,6 +61,7 @@ pkgCache::Header::Header() HeaderSz = sizeof(pkgCache::Header); GroupSz = sizeof(pkgCache::Group); PackageSz = sizeof(pkgCache::Package); + ReleaseFileSz = sizeof(pkgCache::ReleaseFile); PackageFileSz = sizeof(pkgCache::PackageFile); VersionSz = sizeof(pkgCache::Version); DescriptionSz = sizeof(pkgCache::Description); @@ -74,6 +75,7 @@ pkgCache::Header::Header() VersionCount = 0; DescriptionCount = 0; DependsCount = 0; + ReleaseFileCount = 0; PackageFileCount = 0; VerFileCount = 0; DescFileCount = 0; @@ -82,6 +84,7 @@ pkgCache::Header::Header() MaxDescFileSize = 0; FileList = 0; + RlsFileList = 0; #if APT_PKG_ABI < 413 APT_IGNORE_DEPRECATED(StringList = 0;) #endif @@ -102,6 +105,7 @@ 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 && @@ -140,6 +144,7 @@ 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(); @@ -814,7 +819,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 +833,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; } @@ -861,27 +866,27 @@ string pkgCache::VerIterator::RelStr() const 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) + pkgCache::PkgFileIterator const File2 = J.File(); + if (File2.Label() == 0 || File.Label() == 0) continue; if (strcmp(File.Label(),File2.Label()) != 0) continue; - if (File2->Version == File->Version) + if (File2.Version() == File.Version()) { Seen = true; break; } - if (File2->Version == 0 || File->Version == 0) + if (File2.Version() == 0 || File.Version() == 0) break; if (strcmp(File.Version(),File2.Version()) == 0) Seen = true; @@ -895,12 +900,12 @@ string pkgCache::VerIterator::RelStr() const else First = false; - if (File->Label != 0) + if (File.Label() != 0) Res = Res + File.Label() + ':'; - if (File->Archive != 0) + if (File.Archive() != 0) { - if (File->Version == 0) + if (File.Version() == 0) Res += File.Archive(); else Res = Res + File.Version() + '/' + File.Archive(); @@ -908,7 +913,7 @@ string pkgCache::VerIterator::RelStr() const else { // No release file, print the host name that this came from - if (File->Site == 0 || File.Site()[0] == 0) + if (File.Site() == 0 || File.Site()[0] == 0) Res += "localhost"; else Res += File.Site(); @@ -931,12 +936,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 +953,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 +967,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; diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h index b4d56611a..696b3b94d 100644 --- a/apt-pkg/pkgcache.h +++ b/apt-pkg/pkgcache.h @@ -133,6 +133,7 @@ class pkgCache /*{{{*/ struct Header; struct Group; struct Package; + struct ReleaseFile; struct PackageFile; struct Version; struct Description; @@ -150,6 +151,7 @@ class pkgCache /*{{{*/ class DescIterator; class DepIterator; class PrvIterator; + class RlsFileIterator; class PkgFileIterator; class VerFileIterator; class DescFileIterator; @@ -192,9 +194,11 @@ class pkgCache /*{{{*/ enum PkgFlags {Auto=(1<<0),Essential=(1<<3),Important=(1<<4)}; enum PkgFFlags { NotSource=(1<<0), /*!< packages can't be fetched from here, e.g. dpkg/status file */ - NotAutomatic=(1<<1), /*!< archive has a default pin of 1 */ - ButAutomaticUpgrades=(1<<2), /*!< (together with the previous) archive has a default pin of 100 */ - LocalSource=(1<<3), /*!< local sources can't and will not be verified by hashes */ + LocalSource=(1<<1), /*!< local sources can't and will not be verified by hashes */ + }; + 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 */ }; }; @@ -215,6 +219,7 @@ class pkgCache /*{{{*/ Package *PkgP; VerFile *VerFileP; DescFile *DescFileP; + ReleaseFile *RlsFileP; PackageFile *PkgFileP; Version *VerP; Description *DescP; @@ -247,6 +252,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(); @@ -296,6 +303,7 @@ struct pkgCache::Header unsigned short HeaderSz; unsigned short GroupSz; unsigned short PackageSz; + unsigned short ReleaseFileSz; unsigned short PackageFileSz; unsigned short VersionSz; unsigned short DescriptionSz; @@ -314,6 +322,7 @@ struct pkgCache::Header map_id_t VersionCount; map_id_t DescriptionCount; map_id_t DependsCount; + map_fileid_t ReleaseFileCount; map_fileid_t PackageFileCount; map_fileid_t VerFileCount; map_fileid_t DescFileCount; @@ -324,6 +333,9 @@ 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; + /** \brief index of the first ReleaseFile structure */ + map_pointer_t RlsFileList; + #if APT_PKG_ABI < 413 APT_DEPRECATED map_pointer_t StringList; #endif @@ -482,15 +494,14 @@ struct pkgCache::Package unsigned long 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 @@ -498,13 +509,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 */ + unsigned long Flags; + + // Linked list + /** \brief Link to the next ReleaseFile in the Cache */ + map_pointer_t NextFile; + /** \brief unique sequel ID */ + should_be_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 */ @@ -744,6 +789,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 /*{{{*/ @@ -755,6 +805,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..2d0e3960d 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -54,10 +54,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), FoundFileDeps(0) { - CurrentFile = 0; - if (_error->PendingError() == true) return; @@ -145,6 +143,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::const_iterator i = Dynamic::toReMap.begin(); i != Dynamic::toReMap.end(); ++i) @@ -167,6 +166,9 @@ void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newM for (std::vector::const_iterator i = Dynamic::toReMap.begin(); i != Dynamic::toReMap.end(); ++i) (*i)->ReMap(oldMap, newMap); + for (std::vector::const_iterator i = Dynamic::toReMap.begin(); + i != Dynamic::toReMap.end(); ++i) + (*i)->ReMap(oldMap, newMap); } /*}}}*/ // CacheGenerator::WriteStringInMap /*{{{*/ map_stringitem_t pkgCacheGenerator::WriteStringInMap(const char *String, @@ -1072,13 +1074,47 @@ bool pkgCacheGenerator::ListParser::SameVersion(unsigned short const Hash,/*{{{* 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 &Component, + unsigned long const Flags) { // Get some space for the structure map_pointer_t const idxFile = AllocateInMap(sizeof(*CurrentFile)); @@ -1088,18 +1124,24 @@ 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; + 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++; @@ -1174,35 +1216,59 @@ static bool CheckValidity(const string &CacheFile, _error->Discard(); return false; } - + + SPtrArray RlsVisited = new bool[Cache.HeaderP->ReleaseFileCount]; + memset(RlsVisited,0,sizeof(*RlsVisited)*Cache.HeaderP->ReleaseFileCount); + std::vector Files; + for (pkgSourceList::const_iterator i = List.begin(); i != List.end(); ++i) + { + if (Debug == true) + std::clog << "Checking RlsFile " << (*i)->Describe() << ": "; + pkgCache::RlsFileIterator const RlsFile = (*i)->FindInCache(Cache); + if (RlsFile.end() == true) + { + if (Debug == true) + std::clog << "FindInCache returned end-Pointer" << std::endl; + return false; + } + + RlsVisited[RlsFile->ID] = true; + if (Debug == true) + std::clog << "with ID " << RlsFile->ID << " is valid" << std::endl; + + std::vector *Indexes = (*i)->GetIndexFiles(); + for (std::vector::const_iterator j = Indexes->begin(); j != Indexes->end(); ++j) + if ((*j)->HasPackages()) + Files.push_back (*j); + } + 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; + } + + for (; Start != End; ++Start) + Files.push_back(*Start); + /* 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 Visited = new bool[Cache.HeaderP->PackageFileCount]; memset(Visited,0,sizeof(*Visited)*Cache.HeaderP->PackageFileCount); - for (; Start != End; ++Start) + for (std::vector::const_reverse_iterator PkgFile = Files.rbegin(); PkgFile != Files.rend(); ++PkgFile) { if (Debug == true) - std::clog << "Checking PkgFile " << (*Start)->Describe() << ": "; - if ((*Start)->HasPackages() == false) - { - if (Debug == true) - std::clog << "Has NO packages" << std::endl; - continue; - } - - if ((*Start)->Exists() == false) + 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 +1280,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) @@ -1243,9 +1309,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 *Indexes = (*i)->GetIndexFiles(); + for (std::vector::const_iterator j = Indexes->begin(); j != Indexes->end(); ++j) + if ((*j)->HasPackages() == true) + TotalSize += (*j)->Size(); + } + } + for (; Start < End; ++Start) { if ((*Start)->HasPackages() == false) @@ -1261,11 +1338,63 @@ static map_filesize_t ComputeSize(FileIterator Start,FileIterator End) static bool BuildCache(pkgCacheGenerator &Gen, OpProgress *Progress, map_filesize_t &CurrentSize,map_filesize_t TotalSize, + pkgSourceList const * const List, FileIterator Start, FileIterator End) { + std::vector Files; + bool const HasFileDeps = Gen.HasFileDeps(); + + if (List != NULL) + { + for (pkgSourceList::const_iterator i = List->begin(); i != List->end(); ++i) + { + if ((*i)->FindInCache(Gen.GetCache()).end() == false) + { + _error->Warning("Duplicate sources.list entry %s", + (*i)->Describe().c_str()); + continue; + } + + if ((*i)->Merge(Gen, Progress) == false) + return false; + + std::vector *Indexes = (*i)->GetIndexFiles(); + for (std::vector::const_iterator I = Indexes->begin(); I != Indexes->end(); ++I) + { + if (HasFileDeps) + Files.push_back(*I); + + if ((*I)->HasPackages() == false) + continue; + + if ((*I)->Exists() == false) + continue; + + if ((*I)->FindInCache(Gen.GetCache()).end() == false) + { + _error->Warning("Duplicate sources.list entry %s", + (*I)->Describe().c_str()); + continue; + } + + map_filesize_t Size = (*I)->Size(); + if (Progress != NULL) + Progress->OverallProgress(CurrentSize,TotalSize,Size,_("Reading package lists")); + CurrentSize += Size; + + if ((*I)->Merge(Gen,Progress) == false) + return false; + } + } + } + + Gen.SelectReleaseFile("", ""); FileIterator I; for (I = Start; I != End; ++I) { + if (HasFileDeps) + Files.push_back(*I); + if ((*I)->HasPackages() == false) continue; @@ -1288,13 +1417,13 @@ static bool BuildCache(pkgCacheGenerator &Gen, return false; } - if (Gen.HasFileDeps() == true) + if (HasFileDeps == true) { if (Progress != NULL) Progress->Done(); - TotalSize = ComputeSize(Start, End); + TotalSize = ComputeSize(List, Start, End); CurrentSize = 0; - for (I = Start; I != End; ++I) + for (std::vector::const_iterator I = Files.begin(); I != Files.end(); ++I) { map_filesize_t Size = (*I)->Size(); if (Progress != NULL) @@ -1339,6 +1468,7 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress bool const Debug = _config->FindB("Debug::pkgCacheGen", false); std::vector Files; + /* for (std::vector::const_iterator i = List.begin(); i != List.end(); ++i) @@ -1349,8 +1479,7 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress ++j) Files.push_back (*j); } - - map_filesize_t const EndOfSource = Files.size(); +*/ if (_system->AddStatusFiles(Files) == false) return false; @@ -1442,8 +1571,8 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress // 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) + if (CheckValidity(SrcCacheFile, List, Files.end(), + Files.end()) == true) { if (Debug == true) std::clog << "srcpkgcache.bin is valid - populate MMap with it." << std::endl; @@ -1455,28 +1584,28 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress SCacheF.Size()) == false) return false; - TotalSize = ComputeSize(Files.begin()+EndOfSource,Files.end()); + TotalSize = ComputeSize(NULL, Files.begin(), Files.end()); // 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) + if (BuildCache(Gen, Progress, CurrentSize, TotalSize, NULL, + Files.begin(),Files.end()) == false) return false; } else { if (Debug == true) std::clog << "srcpkgcache.bin is NOT valid - rebuild" << std::endl; - TotalSize = ComputeSize(Files.begin(),Files.end()); + TotalSize = ComputeSize(&List, 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) + if (BuildCache(Gen, Progress, CurrentSize, TotalSize, &List, + Files.end(),Files.end()) == false) return false; // Write it back @@ -1503,8 +1632,8 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress } // Build the status cache - 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 (Debug == true) @@ -1536,7 +1665,6 @@ APT_DEPRECATED bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **Ou bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **OutMap) { std::vector Files; - map_filesize_t EndOfSource = Files.size(); if (_system->AddStatusFiles(Files) == false) return false; @@ -1544,7 +1672,7 @@ bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **O 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) @@ -1552,8 +1680,8 @@ bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **O 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) diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h index c4ace713d..2795d09d6 100644 --- a/apt-pkg/pkgcachegen.h +++ b/apt-pkg/pkgcachegen.h @@ -69,7 +69,9 @@ class APT_HIDDEN pkgCacheGenerator /*{{{*/ DynamicMMap ⤅ pkgCache Cache; OpProgress *Progress; - + + std::string RlsFileName; + pkgCache::ReleaseFile *CurrentRlsFile; std::string PkgFileName; pkgCache::PackageFile *CurrentFile; @@ -100,12 +102,14 @@ 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 &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() {return pkgCache::PkgFileIterator(Cache,CurrentFile);}; + inline pkgCache::RlsFileIterator GetCurRlsFile() + {return pkgCache::RlsFileIterator(Cache,CurrentRlsFile);}; bool HasFileDeps() {return FoundFileDeps;}; bool MergeFileProvides(ListParser &List); diff --git a/apt-pkg/policy.cc b/apt-pkg/policy.cc index 00693ce54..bd40ad2d9 100644 --- a/apt-pkg/policy.cc +++ b/apt-pkg/policy.cc @@ -63,9 +63,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,11 +86,11 @@ 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; } @@ -170,8 +170,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]; diff --git a/apt-pkg/versionmatch.cc b/apt-pkg/versionmatch.cc index 284098bdf..86c1b7d4a 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); @@ -178,13 +181,16 @@ pkgCache::VerIterator pkgVersionMatch::Find(pkgCache::PkgIterator Pkg) // This will be Ended by now. return Ver; } + /*}}}*/ #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 +236,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 +267,14 @@ bool pkgVersionMatch::FileMatch(pkgCache::PkgFileIterator File) if (Type == Origin) { if (OrSite.empty() == false) { - if (File->Site == 0) + if (File.Site() == NULL) 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 + { + pkgCache::RlsFileIterator const RlsFile = File.ReleaseFile(); + if (strcmp(File.Site(),"") == 0 && RlsFile->Archive != 0 && strcmp(RlsFile.Archive(),"now") == 0) // skip the status 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..bb950b9c7 100644 --- a/apt-pkg/versionmatch.h +++ b/apt-pkg/versionmatch.h @@ -70,8 +70,8 @@ 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); -- cgit v1.2.3 From 3fd89e62e985c89b1f9a545ab72c20987b756aff Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 12 Jun 2015 12:06:29 +0200 Subject: implement default apt-get file --release-info mode Selecting targets based on the Release they belong to isn't to unrealistic. In fact, it is assumed to be the most used case so it is made the default especially as this allows to bundle another thing we have to be careful with: Filenames and only showing targets we have acquired. Closes: 752702 --- apt-pkg/deb/debmetaindex.cc | 4 ++-- apt-pkg/deb/debmetaindex.h | 2 +- apt-pkg/indexfile.cc | 12 ++++++++++++ apt-pkg/indexfile.h | 1 + apt-pkg/metaindex.cc | 2 +- apt-pkg/metaindex.h | 2 +- apt-pkg/pkgcachegen.cc | 4 ++-- 7 files changed, 20 insertions(+), 7 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 994b95849..b328fcea8 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -422,7 +422,7 @@ bool debReleaseIndex::Merge(pkgCacheGenerator &Gen,OpProgress * /*Prog*/) const/ } /*}}}*/ // ReleaseIndex::FindInCache - Find this index /*{{{*/ -pkgCache::RlsFileIterator debReleaseIndex::FindInCache(pkgCache &Cache) const +pkgCache::RlsFileIterator debReleaseIndex::FindInCache(pkgCache &Cache, bool const ModifyCheck) const { std::string ReleaseFile; bool const releaseExists = ReleaseFileName(this, ReleaseFile); @@ -434,7 +434,7 @@ pkgCache::RlsFileIterator debReleaseIndex::FindInCache(pkgCache &Cache) const continue; // empty means the file does not exist by "design" - if (releaseExists == false && File->Size == 0) + if (ModifyCheck == false || (releaseExists == false && File->Size == 0)) return File; struct stat St; diff --git a/apt-pkg/deb/debmetaindex.h b/apt-pkg/deb/debmetaindex.h index 7e9942710..b448ecc53 100644 --- a/apt-pkg/deb/debmetaindex.h +++ b/apt-pkg/deb/debmetaindex.h @@ -51,7 +51,7 @@ class APT_HIDDEN debReleaseIndex : public metaIndex { virtual std::vector GetIndexTargets() const; virtual std::string Describe() const; - virtual pkgCache::RlsFileIterator FindInCache(pkgCache &Cache) const; + virtual pkgCache::RlsFileIterator FindInCache(pkgCache &Cache, bool const ModifyCheck) const; virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const; std::string MetaIndexInfo(const char *Type) const; diff --git a/apt-pkg/indexfile.cc b/apt-pkg/indexfile.cc index 33fb48e35..605bbeb47 100644 --- a/apt-pkg/indexfile.cc +++ b/apt-pkg/indexfile.cc @@ -137,6 +137,18 @@ std::string IndexTarget::Option(OptionKeys const EnumKey) const /*{{{*/ 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 const types = APT::Configuration::getCompressionTypes(); + for (std::vector::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::const_iterator const M = Options.find(Key); if (M == Options.end()) diff --git a/apt-pkg/indexfile.h b/apt-pkg/indexfile.h index 220c415ac..042e5c2f7 100644 --- a/apt-pkg/indexfile.h +++ b/apt-pkg/indexfile.h @@ -81,6 +81,7 @@ class IndexTarget /*{{{*/ CREATED_BY, TARGET_OF, FILENAME, + EXISTING_FILENAME, }; std::string Option(OptionKeys const Key) const; std::string Format(std::string format) const; diff --git a/apt-pkg/metaindex.cc b/apt-pkg/metaindex.cc index 35ab6c53b..3c1b696bd 100644 --- a/apt-pkg/metaindex.cc +++ b/apt-pkg/metaindex.cc @@ -28,7 +28,7 @@ std::string metaIndex::Describe() const return "Release"; } -pkgCache::RlsFileIterator metaIndex::FindInCache(pkgCache &Cache) const +pkgCache::RlsFileIterator metaIndex::FindInCache(pkgCache &Cache, bool const) const { return pkgCache::RlsFileIterator(Cache); } diff --git a/apt-pkg/metaindex.h b/apt-pkg/metaindex.h index 20c879a89..e1810fb27 100644 --- a/apt-pkg/metaindex.h +++ b/apt-pkg/metaindex.h @@ -54,7 +54,7 @@ class metaIndex virtual bool IsTrusted() const = 0; virtual std::string Describe() const; - virtual pkgCache::RlsFileIterator FindInCache(pkgCache &Cache) const; + 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, diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index 2d0e3960d..9db4ef41f 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -1224,7 +1224,7 @@ static bool CheckValidity(const string &CacheFile, { if (Debug == true) std::clog << "Checking RlsFile " << (*i)->Describe() << ": "; - pkgCache::RlsFileIterator const RlsFile = (*i)->FindInCache(Cache); + pkgCache::RlsFileIterator const RlsFile = (*i)->FindInCache(Cache, true); if (RlsFile.end() == true) { if (Debug == true) @@ -1348,7 +1348,7 @@ static bool BuildCache(pkgCacheGenerator &Gen, { for (pkgSourceList::const_iterator i = List->begin(); i != List->end(); ++i) { - if ((*i)->FindInCache(Gen.GetCache()).end() == false) + if ((*i)->FindInCache(Gen.GetCache(), false).end() == false) { _error->Warning("Duplicate sources.list entry %s", (*i)->Describe().c_str()); -- cgit v1.2.3 From e185d8b3e39e3840f439cab7d5d265fd96d84c6f Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 12 Jun 2015 14:42:17 +0200 Subject: populate the Architecture field for PackageFiles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is mainly visible in the policy, so that you can now pin by b= and let it only effect Packages files of this architecture and hence the packages coming from it (which do not need to be from this architecture, but very likely are in a normal repository setup). If you should pin by architecture in this way is a different question… Closes: 687255 --- apt-pkg/deb/debindexfile.cc | 8 ++++---- apt-pkg/edsp/edspindexfile.cc | 2 +- apt-pkg/pkgcachegen.cc | 10 ++++++++++ apt-pkg/pkgcachegen.h | 2 +- 4 files changed, 16 insertions(+), 6 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index 3a79cbc58..f089cda81 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -128,7 +128,7 @@ bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const if (Dist.empty()) Dist = "/"; ::URI Tmp(URI); - if (Gen.SelectFile(PackageFile, *this, Target.Option(IndexTarget::COMPONENT)) == false) + if (Gen.SelectFile(PackageFile, *this, Target.Option(IndexTarget::ARCHITECTURE), Target.Option(IndexTarget::COMPONENT)) == false) return _error->Error("Problem with SelectFile %s",PackageFile.c_str()); // Store the IMS information @@ -203,7 +203,7 @@ bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const if (Prog != NULL) Prog->SubProgress(0, Target.Description); - if (Gen.SelectFile(TranslationFile, *this, Target.Option(IndexTarget::COMPONENT), pkgCache::Flag::NotSource) == false) + if (Gen.SelectFile(TranslationFile, *this, "", Target.Option(IndexTarget::COMPONENT), pkgCache::Flag::NotSource) == false) return _error->Error("Problem with SelectFile %s",TranslationFile.c_str()); // Store the IMS information @@ -284,7 +284,7 @@ bool debStatusIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const if (Prog != NULL) Prog->SubProgress(0,File); - if (Gen.SelectFile(File, *this, "now", pkgCache::Flag::NotSource) == false) + if (Gen.SelectFile(File, *this, "", "now", pkgCache::Flag::NotSource) == false) return _error->Error("Problem with SelectFile %s",File.c_str()); // Store the IMS information @@ -409,7 +409,7 @@ bool debDebPkgFileIndex::Merge(pkgCacheGenerator& Gen, OpProgress* Prog) const // and give it to the list parser debDebFileParser Parser(DebControl, DebFile); - if(Gen.SelectFile(DebFile, *this, "now", pkgCache::Flag::LocalSource) == false) + if(Gen.SelectFile(DebFile, *this, "", "now", pkgCache::Flag::LocalSource) == false) return _error->Error("Problem with SelectFile %s", DebFile.c_str()); pkgCache::PkgFileIterator File = Gen.GetCurFile(); diff --git a/apt-pkg/edsp/edspindexfile.cc b/apt-pkg/edsp/edspindexfile.cc index 43dd44a79..a2ec0a19b 100644 --- a/apt-pkg/edsp/edspindexfile.cc +++ b/apt-pkg/edsp/edspindexfile.cc @@ -49,7 +49,7 @@ bool edspIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const if (Prog != NULL) Prog->SubProgress(0,File); - if (Gen.SelectFile(File, *this, "edsp") == false) + if (Gen.SelectFile(File, *this, "", "edsp") == false) return _error->Error("Problem with SelectFile %s",File.c_str()); // Store the IMS information diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index 9db4ef41f..ea0205944 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -1113,6 +1113,7 @@ bool pkgCacheGenerator::SelectReleaseFile(const string &File,const string &Site, added versions. The caller is responsible for setting the IMS fields. */ bool pkgCacheGenerator::SelectFile(std::string const &File, pkgIndexFile const &Index, + std::string const &Architecture, std::string const &Component, unsigned long const Flags) { @@ -1133,6 +1134,15 @@ bool pkgCacheGenerator::SelectFile(std::string const &File, 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; diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h index 2795d09d6..ade93795b 100644 --- a/apt-pkg/pkgcachegen.h +++ b/apt-pkg/pkgcachegen.h @@ -102,7 +102,7 @@ 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,pkgIndexFile const &Index, std::string const &Component, 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;}; -- cgit v1.2.3 From d2cb5b153fb13d587b1ff632cab34ce0c403326e Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 12 Jun 2015 15:48:00 +0200 Subject: hide Translation-* in 'apt-cache policy' output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Translation-* files are internally handled as PackageFiles which isn't super nice, but giving them their own struct is a bit overkill so let it be for the moment. They always appeared in the policy output because of this through and now that they are properly linked to a ReleaseFile they even display all the pinning information on them, but they don't contain any packages which could be pinned… No problem, but useless and potentially confusing output. Adding a 'NoPackages' flag which can be set on those files and be used in applications seems like a simple way to fix this display issue. --- apt-pkg/deb/debindexfile.cc | 2 +- apt-pkg/pkgcache.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index f089cda81..944cbe0bf 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -203,7 +203,7 @@ bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const if (Prog != NULL) Prog->SubProgress(0, Target.Description); - if (Gen.SelectFile(TranslationFile, *this, "", Target.Option(IndexTarget::COMPONENT), pkgCache::Flag::NotSource) == false) + if (Gen.SelectFile(TranslationFile, *this, "", Target.Option(IndexTarget::COMPONENT), pkgCache::Flag::NotSource | pkgCache::Flag::NoPackages) == false) return _error->Error("Problem with SelectFile %s",TranslationFile.c_str()); // Store the IMS information diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h index 696b3b94d..3cc85f1e8 100644 --- a/apt-pkg/pkgcache.h +++ b/apt-pkg/pkgcache.h @@ -195,6 +195,7 @@ class pkgCache /*{{{*/ 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 */ -- cgit v1.2.3 From d56e2917f27a722b54685de13aeb1bb7592fc61b Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 13 Jun 2015 11:13:45 +0200 Subject: provide a public interface for acquiring changelogs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Provided is a specialized acquire item which given a version can figure out the correct URI to try by itself and if not provides an error message alongside with static methods to get just the URI it would try to download if it should just be displayed or similar such. The URI is constructed as follows: Release files can provide an URI template in the "Changelogs" field, otherwise we lookup a configuration item based on the "Label" or "Origin" of the Release file to get a (hopefully known) default value for now. This template should contain the string CHANGEPATH which is replaced with the information about the version we want the changelog for (e.g. main/a/apt/apt_1.1). This middleway was choosen as this path part was consistent over the three known implementations (+1 defunct), while the rest of the URI varies widely between them. The benefit of this construct is that it is now easy to get changelogs for Debian packages on Ubuntu and vice versa – even at the moment where the Changelogs field is present nowhere. Strictly better than what apt-get had before as it would even fail to get changelogs from security… Now it will notice that security identifies as Origin: Debian and pick this setting (assuming again that no Changelogs field exists). If on the other hand security would ship its changelogs in a different location we could set it via the Label option overruling Origin. Closes: 687147, 739854, 784027, 787190 --- apt-pkg/acquire-item.cc | 211 ++++++++++++++++++++++++++++++++++++++++++++++++ apt-pkg/acquire-item.h | 114 ++++++++++++++++++++++++++ apt-pkg/init.cc | 4 + 3 files changed, 329 insertions(+) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index d6e9ccbe0..4bf4e62f8 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -2836,6 +2837,216 @@ std::string pkgAcqArchive::ShortDesc() const /*{{{*/ } /*}}}*/ +// 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); + + if (Status == StatDone) // this happens if we queue the same changelog two times + { + Complete = true; + for (pkgAcquire::UriIterator I = Owner->UriBegin(); I != Owner->UriEnd(); ++I) + if (I->URI == Desc.URI) + if (DestFile != I->Owner->DestFile) + if (symlink(I->Owner->DestFile.c_str(), DestFile.c_str()) != 0) + { + ; // ignore error, there isn't anthing we could do to handle the edgecase of an edgecase + } + } +} + /*}}}*/ +std::string pkgAcqChangelog::URI(pkgCache::VerIterator const &Ver) /*{{{*/ +{ + char const * const SrcName = Ver.SourcePkgName(); + char const * const SrcVersion = Ver.SourceVerStr(); + pkgCache::PkgFileIterator PkgFile; + // find the first source for this version which promises a changelog + for (pkgCache::VerFileIterator VF = Ver.FileList(); VF.end() == false; ++VF) + { + pkgCache::PkgFileIterator const PF = VF.File(); + if (PF.Flagged(pkgCache::Flag::NotSource) || PF->Release == 0) + continue; + PkgFile = PF; + pkgCache::RlsFileIterator const RF = PF.ReleaseFile(); + std::string const uri = URI(RF, PF.Component(), SrcName, SrcVersion); + if (uri.empty()) + continue; + return uri; + } + return ""; +} +std::string pkgAcqChangelog::URITemplate(pkgCache::RlsFileIterator const &Rls) +{ + if (Rls.end() == true || (Rls->Label == 0 && Rls->Origin == 0)) + return ""; + std::string const serverConfig = "Acquire::Changelogs::URI"; + std::string server; +#define APT_EMPTY_SERVER \ + if (server.empty() == false) \ + { \ + if (server != "no") \ + return server; \ + return ""; \ + } +#define APT_CHECK_SERVER(X, Y) \ + if (Rls->X != 0) \ + { \ + std::string const specialServerConfig = serverConfig + "::" + Y + #X + "::" + Rls.X(); \ + server = _config->Find(specialServerConfig); \ + APT_EMPTY_SERVER \ + } + // this way e.g. Debian-Security can fallback to Debian + APT_CHECK_SERVER(Label, "Override::") + APT_CHECK_SERVER(Origin, "Override::") + + if (RealFileExists(Rls.FileName())) + { + _error->PushToStack(); + FileFd rf; + /* This can be costly. A caller wanting to get millions of URIs might + want to do this on its own once and use Override settings. + We don't do this here as Origin/Label are not as unique as they + should be so this could produce request order-dependent anomalies */ + if (OpenMaybeClearSignedFile(Rls.FileName(), rf) == true) + { + pkgTagFile TagFile(&rf, rf.Size()); + pkgTagSection Section; + if (TagFile.Step(Section) == true) + server = Section.FindS("Changelogs"); + } + _error->RevertToStack(); + APT_EMPTY_SERVER + } + + APT_CHECK_SERVER(Label, "") + APT_CHECK_SERVER(Origin, "") +#undef APT_CHECK_SERVER +#undef APT_EMPTY_SERVER + return ""; +} +std::string pkgAcqChangelog::URI(pkgCache::RlsFileIterator const &Rls, + char const * const Component, char const * const SrcName, + char const * const SrcVersion) +{ + return URI(URITemplate(Rls), Component, SrcName, SrcVersion); +} +std::string pkgAcqChangelog::URI(std::string const &Template, + char const * const Component, char const * const SrcName, + char const * const SrcVersion) +{ + if (Template.find("CHANGEPATH") == std::string::npos) + return ""; + + // the path is: COMPONENT/SRC/SRCNAME/SRCNAME_SRCVER, e.g. main/a/apt/1.1 or contrib/liba/libapt/2.0 + std::string Src = SrcName; + std::string path = APT::String::Startswith(SrcName, "lib") ? Src.substr(0, 4) : Src.substr(0,1); + path.append("/").append(Src).append("/"); + path.append(Src).append("_").append(StripEpoch(SrcVersion)); + // we omit component for releases without one (= flat-style repositories) + if (Component != NULL && strlen(Component) != 0) + path = std::string(Component) + "/" + path; + + return SubstVar(Template, "CHANGEPATH", path); +} + /*}}}*/ +// AcqChangelog::Failed - Failure handler /*{{{*/ +void pkgAcqChangelog::Failed(string const &Message, pkgAcquire::MethodConfig const * const Cnf) +{ + Item::Failed(Message,Cnf); + + std::string errText; + // TRANSLATOR: %s=%s is sourcename=sourceversion, e.g. apt=1.1 + strprintf(errText, _("Changelog unavailable for %s=%s"), SrcName.c_str(), SrcVersion.c_str()); + + // Error is probably something techy like 404 Not Found + if (ErrorText.empty()) + ErrorText = errText; + else + ErrorText = errText + " (" + ErrorText + ")"; + return; +} + /*}}}*/ +// AcqChangelog::Done - Item downloaded OK /*{{{*/ +void pkgAcqChangelog::Done(string const &Message,HashStringList const &CalcHashes, + pkgAcquire::MethodConfig const * const Cnf) +{ + Item::Done(Message,CalcHashes,Cnf); + + Complete = true; +} + /*}}}*/ +pkgAcqChangelog::~pkgAcqChangelog() /*{{{*/ +{ + if (TemporaryDirectory.empty() == false) + { + unlink(DestFile.c_str()); + rmdir(TemporaryDirectory.c_str()); + } +} + /*}}}*/ + // AcqFile::pkgAcqFile - Constructor /*{{{*/ pkgAcqFile::pkgAcqFile(pkgAcquire * const Owner,string const &URI, HashStringList const &Hashes, unsigned long long const Size,string const &Dsc,string const &ShortDesc, diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index b6d569737..606fd4173 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -1031,6 +1031,120 @@ class pkgAcqArchive : public pkgAcquire::Item std::string &StoreFilename); }; /*}}}*/ +/** \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 *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 { return HashStringList(); } + virtual bool HashesRequired() const { return false; } + + // Specialized action members + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); + virtual void Done(std::string const &Message, HashStringList const &CalcHashes, + pkgAcquire::MethodConfig const * const Cnf); + virtual std::string DescURI() const {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. {{{ * * The file is retrieved even if it is accessed via a URL type that diff --git a/apt-pkg/init.cc b/apt-pkg/init.cc index e2239a906..96966b249 100644 --- a/apt-pkg/init.cc +++ b/apt-pkg/init.cc @@ -119,6 +119,10 @@ bool pkgInitConfig(Configuration &Cnf) Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::flatDescription", "$(SITE) $(RELEASE) Sources"); Cnf.CndSet("APT::Acquire::Targets::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::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 -- cgit v1.2.3 From 08ea7806458de0995414eaae852e0a5985875642 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 15 Jun 2015 13:16:43 +0200 Subject: deal better with acquiring the same URI multiple times This is an unlikely event for indexes and co, but it can happen quiet easily e.g. for changelogs where you want to get the changelogs for multiple binary package(version)s which happen to all be built from a single source. The interesting part is that the Acquire system actually detected this already and set the item requesting the URI again to StatDone - expect that this is hardly sufficient: an Item must be Complete=true as well to be considered truely done and that is only the tip of the ::Done handling iceberg. So instead of this StatDone hack we allow QItems to be owned by multiple items and notify all owners about everything now, so that for the point of each item they got it downloaded just for them. --- apt-pkg/acquire-item.cc | 25 ++--- apt-pkg/acquire-item.h | 1 + apt-pkg/acquire-worker.cc | 280 ++++++++++++++++++++++++++++------------------ apt-pkg/acquire-worker.h | 3 + apt-pkg/acquire.cc | 126 ++++++++++++++++++--- apt-pkg/acquire.h | 44 ++++++-- 6 files changed, 328 insertions(+), 151 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 4bf4e62f8..dc4f61b56 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -438,6 +438,11 @@ APT_PURE pkgAcquire * pkgAcquire::Item::GetOwner() const /*{{{*/ return Owner; } /*}}}*/ +pkgAcquire::ItemDesc &pkgAcquire::Item::GetItemDesc() /*{{{*/ +{ + return Desc; +} + /*}}}*/ APT_CONST bool pkgAcquire::Item::IsTrusted() const /*{{{*/ { return false; @@ -840,7 +845,7 @@ bool pkgAcqMetaBase::CheckDownloadDone(pkgAcqTransactionItem * const I, const st return false; } - if (FileName != I->DestFile) + if (FileName != I->DestFile && RealFileExists(I->DestFile) == false) { I->Local = true; I->Desc.URI = "copy:" + FileName; @@ -2482,7 +2487,7 @@ void pkgAcqIndex::StageDownloadDone(string const &Message, HashStringList const // 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; @@ -2760,7 +2765,7 @@ void pkgAcqArchive::Done(string const &Message, HashStringList const &Hashes, } // Reference filename - if (FileName != DestFile) + if (DestFile != FileName && RealFileExists(DestFile) == false) { StoreFilename = DestFile = FileName; Local = true; @@ -2903,18 +2908,6 @@ void pkgAcqChangelog::Init(std::string const &DestDir, std::string const &DestFi strprintf(Desc.Description, "%s %s %s Changelog", URI::SiteOnly(Desc.URI).c_str(), SrcName.c_str(), SrcVersion.c_str()); Desc.Owner = this; QueueURI(Desc); - - if (Status == StatDone) // this happens if we queue the same changelog two times - { - Complete = true; - for (pkgAcquire::UriIterator I = Owner->UriBegin(); I != Owner->UriEnd(); ++I) - if (I->URI == Desc.URI) - if (DestFile != I->Owner->DestFile) - if (symlink(I->Owner->DestFile.c_str(), DestFile.c_str()) != 0) - { - ; // ignore error, there isn't anthing we could do to handle the edgecase of an edgecase - } - } } /*}}}*/ std::string pkgAcqChangelog::URI(pkgCache::VerIterator const &Ver) /*{{{*/ @@ -3107,7 +3100,7 @@ void pkgAcqFile::Done(string const &Message,HashStringList const &CalcHashes, 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 || diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index 606fd4173..9dbacc1ea 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -249,6 +249,7 @@ class pkgAcquire::Item : public WeakPointable /*{{{*/ /** \return the acquire process with which this item is associated. */ pkgAcquire *GetOwner() const; + pkgAcquire::ItemDesc &GetItemDesc(); /** \return \b true if this object is being fetched from a trusted source. */ virtual bool IsTrusted() const; diff --git a/apt-pkg/acquire-worker.cc b/apt-pkg/acquire-worker.cc index 099a1f87d..d6318a21b 100644 --- a/apt-pkg/acquire-worker.cc +++ b/apt-pkg/acquire-worker.cc @@ -258,18 +258,27 @@ bool pkgAcquire::Worker::RunMessages() 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) + { + pkgAcquire::Item *Owner = *O; + Owner->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 const ItmOwners = Itm->Owners; OwnerQ->ItemDone(Itm); - OwnerQ->Owner->Enqueue(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(); + desc.URI = NewURI; + OwnerQ->Owner->Enqueue(desc); - if (Log != 0) - Log->Done(Desc); + if (Log != 0) + Log->Done(Owner->GetItemDesc()); + } break; } @@ -286,14 +295,18 @@ bool pkgAcquire::Worker::RunMessages() 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, TotalSize); - - // Display update before completion - if (Log != 0 && Log->MorePulses == true) - Log->Pulse(Itm->Owner->GetOwner()); + for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O) + { + (*O)->Start(Message, TotalSize); - 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; } @@ -307,105 +320,110 @@ bool pkgAcquire::Worker::RunMessages() 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()); + for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O) + Log->Pulse((*O)->GetOwner()); - OwnerQ->ItemDone(Itm); - - HashStringList const ExpectedHashes = Owner->GetExpectedHashes(); - // see if we got hashes to verify + 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)); - } - // not all methods always sent Hashes our way - if (ExpectedHashes.usable() == true && ReceivedHashes.usable() == false) - { - std::string const filename = LookupTag(Message, "Filename", Owner->DestFile.c_str()); - if (filename.empty() == false && RealFileExists(filename)) + // see if we got hashes to verify + for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type) { - Hashes calc(ExpectedHashes); - FileFd file(filename, FileFd::ReadOnly, FileFd::None); - calc.AddFD(file); - ReceivedHashes = calc.GetHashStringList(); + 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; - for (HashStringList::const_iterator hs = ExpectedHashes.begin(); hs != ExpectedHashes.end(); ++hs) - std::clog << "\t- " << hs->toStr() << std::endl; - std::clog << endl; - } + // 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 const ItmOwners = Itm->Owners; + OwnerQ->ItemDone(Itm); + Itm = NULL; - // decide if what we got is what we expected - bool consideredOkay = false; bool const isIMSHit = StringToBool(LookupTag(Message,"IMS-Hit"),false) || StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false); - if (ExpectedHashes.usable()) + + for (pkgAcquire::Queue::QItem::owner_iterator O = ItmOwners.begin(); O != ItmOwners.end(); ++O) { - if (ReceivedHashes.usable() == false) + pkgAcquire::Item * const Owner = *O; + HashStringList const ExpectedHashes = Owner->GetExpectedHashes(); + if(_config->FindB("Debug::pkgAcquire::Auth", false) == true) { - /* 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; + 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; } - else if (ReceivedHashes == ExpectedHashes) - consideredOkay = true; - else - consideredOkay = false; - } - else if (Owner->HashesRequired() == true) - consideredOkay = false; - else - consideredOkay = true; + // decide if what we got is what we expected + bool consideredOkay = false; + if (ExpectedHashes.usable()) + { + 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; - if (consideredOkay == true) - { - Owner->Done(Message, ReceivedHashes, Config); - ItemDone(); + } + else if (Owner->HashesRequired() == true) + consideredOkay = false; + else + consideredOkay = true; - // Log that we are done - if (Log != 0) + if (consideredOkay == true) { - if (isIMSHit) + Owner->Done(Message, ReceivedHashes, Config); + + // Log that we are done + if (Log != 0) { - /* Hide 'hits' for local only sources - we also manage to - hide gets */ - if (Config->LocalOnly == false) - Log->IMSHit(Desc); + if (isIMSHit) + Log->IMSHit(Owner->GetItemDesc()); + else + Log->Done(Owner->GetItemDesc()); } - else - Log->Done(Desc); } - } - else - { - Owner->Status = pkgAcquire::Item::StatAuthError; - Owner->Failed(Message,Config); - ItemDone(); + else + { + Owner->Status = pkgAcquire::Item::StatAuthError; + Owner->Failed(Message,Config); - if (Log != 0) - Log->Fail(Desc); + if (Log != 0) + Log->Fail(Owner->GetItemDesc()); + } } + ItemDone(); break; } @@ -419,30 +437,32 @@ 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 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; } @@ -578,16 +598,24 @@ bool pkgAcquire::Worker::QueueItem(pkgAcquire::Queue::QItem *Item) Message.reserve(300); Message += "URI: " + Item->URI; Message += "\nFilename: " + Item->Owner->DestFile; - HashStringList const hsl = Item->Owner->GetExpectedHashes(); + + 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)) @@ -686,3 +714,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) + { + // diferent 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..3a3ef706d 100644 --- a/apt-pkg/acquire-worker.h +++ b/apt-pkg/acquire-worker.h @@ -326,6 +326,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..14c8863dc 100644 --- a/apt-pkg/acquire.cc +++ b/apt-pkg/acquire.cc @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -682,7 +683,8 @@ bool pkgAcquire::Queue::Enqueue(ItemDesc &Item) for (; *I != 0; I = &(*I)->Next) if (Item.URI == (*I)->URI) { - Item.Owner->Status = Item::StatDone; + (*I)->Owners.push_back(Item.Owner); + Item.Owner->Status = (*I)->Owner->Status; return false; } @@ -705,13 +707,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 +724,7 @@ bool pkgAcquire::Queue::Dequeue(Item *Owner) else I = &(*I)->Next; } - + return Res; } /*}}}*/ @@ -799,9 +801,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 +814,7 @@ bool pkgAcquire::Queue::ItemDone(QItem *Itm) Dequeue(Itm->Owner); Owner->Bump(); } - + return Cycle(); } /*}}}*/ @@ -824,7 +829,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 +837,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,6 +861,94 @@ 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::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::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 /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -914,9 +1008,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; } diff --git a/apt-pkg/acquire.h b/apt-pkg/acquire.h index fc90624e1..02031dafd 100644 --- a/apt-pkg/acquire.h +++ b/apt-pkg/acquire.h @@ -68,9 +68,10 @@ #include #include +#include -#include #include +#include #include #include @@ -390,13 +391,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; }; /*}}}*/ @@ -419,13 +420,26 @@ class pkgAcquire::Queue protected: /** \brief A single item placed in this queue. */ - struct QItem : pkgAcquire::ItemDesc + struct QItem : public WeakPointable { /** \brief The next item in the queue. */ QItem *Next; /** \brief The worker associated with this item, if any. */ pkgAcquire::Worker *Worker; + /** \brief The URI from which to download this item. */ + std::string URI; + /** \brief A description of this item. */ + std::string Description; + /** \brief A shorter description of this item. */ + std::string ShortDesc; + /** \brief The underlying items interested in the download */ + std::vector Owners; + // both, backward compatibility and easy access as syncing is interal + Item * Owner; + + typedef std::vector::const_iterator owner_iterator; + /** \brief Assign the ItemDesc portion of this QItem from * another ItemDesc */ @@ -434,10 +448,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; @@ -590,7 +618,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;}; -- cgit v1.2.3 From ff86d7df6a53ff6283de4b9a858c1dad98ed887f Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 15 Jun 2015 13:36:11 +0200 Subject: call URIStart in cdrom and file method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All other methods call it, so they should follow along even if the work they do afterwards is hardly breathtaking and usually results in a URIDone pretty soon, but the acquire system tells the individual item about this via a virtual method call, so even through none of our existing items contains any critical code in these, maybe one day they might. Consistency at least once… Which is also why this has a good sideeffect: file: and cdrom: requests appear now in the 'apt-get update' output. Finally - it never made sense to hide them for me. Okay, I guess it made before the new hit behavior, but now that you can actually see the difference in an update it makes sense to see if a file: repository changed or not as well. --- apt-pkg/acquire-item.cc | 13 ++++--------- apt-pkg/acquire-worker.cc | 1 - 2 files changed, 4 insertions(+), 10 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index dc4f61b56..50936b627 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -519,19 +519,14 @@ void pkgAcquire::Item::Done(string const &Message, HashStringList const &Hashes, pkgAcquire::MethodConfig const * const /*Cnf*/) { // We just downloaded something.. - string FileName = LookupTag(Message,"Filename"); UsedMirror = LookupTag(Message,"UsedMirror"); - unsigned long long const downloadedSize = Hashes.FileSize(); - if (downloadedSize != 0) + if (FileSize == 0) { - if (Complete == false && !Local && FileName == DestFile) + unsigned long long const downloadedSize = Hashes.FileSize(); + if (downloadedSize != 0) { - if (Owner->Log != 0) - Owner->Log->Fetched(Hashes.FileSize(),atoi(LookupTag(Message,"Resume-Point","0").c_str())); + FileSize = downloadedSize; } - - if (FileSize == 0) - FileSize= downloadedSize; } Status = StatDone; ErrorText = string(); diff --git a/apt-pkg/acquire-worker.cc b/apt-pkg/acquire-worker.cc index d6318a21b..ef195d44b 100644 --- a/apt-pkg/acquire-worker.cc +++ b/apt-pkg/acquire-worker.cc @@ -362,7 +362,6 @@ bool pkgAcquire::Worker::RunMessages() 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) { pkgAcquire::Item * const Owner = *O; -- cgit v1.2.3 From 1eb1836f4b5397497bd34f0cf516e6e4e73117bf Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 15 Jun 2015 16:41:43 +0200 Subject: show item ID in Hit, Ign and Err lines as well Again, consistency is the main sellingpoint here, but this way it is now also easier to explain that some files move through different stages and lines are printed for them hence multiple times: That is a bit hard to believe if the number is changing all the time, but now that it keeps consistent. --- apt-pkg/acquire-item.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 50936b627..5460280ec 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -405,7 +405,7 @@ class APT_HIDDEN NoActionItem : public pkgAcquire::Item /*{{{*/ // Acquire::Item::Item - Constructor /*{{{*/ APT_IGNORE_DEPRECATED_PUSH pkgAcquire::Item::Item(pkgAcquire * const Owner) : - FileSize(0), PartialSize(0), Mode(0), Complete(false), Local(false), + FileSize(0), PartialSize(0), Mode(0), ID(0), Complete(false), Local(false), QueueCounter(0), ExpectedAdditionalItems(0), Owner(Owner) { Owner->Add(this); -- cgit v1.2.3 From 9d2a8a7388cf3b0bbbe92f6b0b30a533e1167f40 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 15 Jun 2015 23:06:56 +0200 Subject: condense parallel requests with the same hashes to one It shouldn't be too common, but sometimes people have multiple mirrors in the sources or otherwise repositories with the same content. Now that we gracefully can handle multiple requests to the same URI, we can also fold multiple requests with the same expected hashes into one. Note that this isn't trying to find oppertunities for merging, but just merges if it happens to encounter the oppertunity for it. This is most obvious in the new testcase actually as it needs to delay the action to give the acquire system enough time to figure out that they can be merged. --- apt-pkg/acquire.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc index 14c8863dc..34afab181 100644 --- a/apt-pkg/acquire.cc +++ b/apt-pkg/acquire.cc @@ -680,9 +680,12 @@ 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()) { + 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; -- cgit v1.2.3 From 533fe3d13927798c17bdef84eba60ed9441d9608 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 15 Jun 2015 23:59:14 +0200 Subject: allow ratelimiting progress reporting for testcases Progress reports once in a while which is a bit to unpredictable for testcases, so we enforce a steady progress for them in the hope that this makes the tests (mostly test-apt-progress-fd) a bit more stable. Git-Dch: Ignore --- apt-pkg/acquire.cc | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc index 34afab181..5e5bec95c 100644 --- a/apt-pkg/acquire.cc +++ b/apt-pkg/acquire.cc @@ -955,7 +955,7 @@ std::string pkgAcquire::Queue::QItem::Custom600Headers() const /*{{{*/ // AcquireStatus::pkgAcquireStatus - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ -pkgAcquireStatus::pkgAcquireStatus() : d(NULL), Percent(0), Update(true), MorePulses(false) +pkgAcquireStatus::pkgAcquireStatus() : d(NULL), Percent(-1), Update(true), MorePulses(false) { Start(); } @@ -1054,13 +1054,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) @@ -1078,11 +1082,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(); -- cgit v1.2.3 From c8a4ce6cbed57ae108dc955d4a850f9b129a0693 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 16 Jun 2015 16:22:46 +0200 Subject: add d-pointer, virtual destructors and de-inline de/constructors To have a chance to keep the ABI for a while we need all three to team up. One of them missing and we might loose, so ensuring that they are available is a very tedious but needed task once in a while. Git-Dch: Ignore --- apt-pkg/acquire-item.cc | 11 +++- apt-pkg/acquire-item.h | 16 ++++-- apt-pkg/acquire-method.cc | 6 +- apt-pkg/acquire-method.h | 9 ++- apt-pkg/acquire-worker.h | 1 - apt-pkg/acquire.cc | 9 +++ apt-pkg/acquire.h | 10 +--- apt-pkg/algorithms.h | 6 +- apt-pkg/aptconfiguration.h | 21 ++++--- apt-pkg/cachefile.h | 1 - apt-pkg/cacheset.cc | 15 ++++- apt-pkg/cacheset.h | 24 +++++--- apt-pkg/cdrom.cc | 6 ++ apt-pkg/cdrom.h | 11 +++- apt-pkg/clean.cc | 1 + apt-pkg/clean.h | 2 + apt-pkg/deb/debindexfile.cc | 1 + apt-pkg/deb/debindexfile.h | 8 ++- apt-pkg/deb/debmetaindex.cc | 2 + apt-pkg/deb/debmetaindex.h | 3 +- apt-pkg/deb/debrecords.cc | 7 +++ apt-pkg/deb/debrecords.h | 15 +++-- apt-pkg/deb/debsrcrecords.cc | 4 ++ apt-pkg/deb/debsrcrecords.h | 4 +- apt-pkg/deb/debversion.h | 1 - apt-pkg/depcache.h | 6 +- apt-pkg/edsp.cc | 123 +++++++++++++++++++++-------------------- apt-pkg/edsp.h | 42 +++++--------- apt-pkg/edsp/edspindexfile.cc | 2 + apt-pkg/edsp/edspindexfile.h | 1 + apt-pkg/edsp/edsplistparser.cc | 2 + apt-pkg/edsp/edsplistparser.h | 2 + apt-pkg/edsp/edspsystem.h | 2 +- apt-pkg/indexcopy.cc | 10 ++++ apt-pkg/indexcopy.h | 23 ++++++-- apt-pkg/indexfile.cc | 3 + apt-pkg/indexfile.h | 6 +- apt-pkg/indexrecords.h | 3 - apt-pkg/install-progress.cc | 6 ++ apt-pkg/install-progress.h | 11 +++- apt-pkg/metaindex.h | 1 + apt-pkg/orderlist.h | 4 +- apt-pkg/packagemanager.h | 2 +- apt-pkg/pkgcache.cc | 2 + apt-pkg/pkgcache.h | 5 +- apt-pkg/pkgcachegen.cc | 3 + apt-pkg/pkgcachegen.h | 17 +++--- apt-pkg/pkgrecords.cc | 3 + apt-pkg/pkgrecords.h | 8 ++- apt-pkg/pkgsystem.cc | 2 + apt-pkg/pkgsystem.h | 5 +- apt-pkg/policy.cc | 2 + apt-pkg/policy.h | 5 +- apt-pkg/sourcelist.h | 4 +- apt-pkg/srcrecords.h | 1 - apt-pkg/tagfile.h | 2 - apt-pkg/version.cc | 3 + apt-pkg/version.h | 2 +- 58 files changed, 322 insertions(+), 185 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 5460280ec..3313aaabc 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -438,7 +438,7 @@ APT_PURE pkgAcquire * pkgAcquire::Item::GetOwner() const /*{{{*/ return Owner; } /*}}}*/ -pkgAcquire::ItemDesc &pkgAcquire::Item::GetItemDesc() /*{{{*/ +APT_CONST pkgAcquire::ItemDesc &pkgAcquire::Item::GetItemDesc() /*{{{*/ { return Desc; } @@ -1098,6 +1098,7 @@ bool pkgAcqMetaBase::VerifyVendor(string const &Message) /*{{{*/ return true; } /*}}}*/ +pkgAcqMetaBase::~pkgAcqMetaBase() {} pkgAcqMetaClearSig::pkgAcqMetaClearSig(pkgAcquire * const Owner, /*{{{*/ IndexTarget const &ClearsignedTarget, @@ -1319,6 +1320,7 @@ std::string pkgAcqMetaIndex::DescURI() const /*{{{*/ return Target.URI; } /*}}}*/ +pkgAcqMetaIndex::~pkgAcqMetaIndex() {} // AcqMetaSig::AcqMetaSig - Constructor /*{{{*/ pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire * const Owner, @@ -1491,6 +1493,7 @@ pkgAcqBaseIndex::pkgAcqBaseIndex(pkgAcquire * const Owner, { } /*}}}*/ +pkgAcqBaseIndex::~pkgAcqBaseIndex() {} // AcqDiffIndex::AcqDiffIndex - Constructor /*{{{*/ // --------------------------------------------------------------------- @@ -1893,6 +1896,7 @@ void pkgAcqDiffIndex::Done(string const &Message,HashStringList const &Hashes, / return; } /*}}}*/ +pkgAcqDiffIndex::~pkgAcqDiffIndex() {} // AcqIndexDiffs::AcqIndexDiffs - Constructor /*{{{*/ // --------------------------------------------------------------------- @@ -2119,6 +2123,7 @@ std::string pkgAcqIndexDiffs::Custom600Headers() const /*{{{*/ return patchhashes.str(); } /*}}}*/ +pkgAcqIndexDiffs::~pkgAcqIndexDiffs() {} // AcqIndexMergeDiffs::AcqIndexMergeDiffs - Constructor /*{{{*/ pkgAcqIndexMergeDiffs::pkgAcqIndexMergeDiffs(pkgAcquire * const Owner, @@ -2263,6 +2268,7 @@ std::string pkgAcqIndexMergeDiffs::Custom600Headers() const /*{{{*/ return patchhashes.str(); } /*}}}*/ +pkgAcqIndexMergeDiffs::~pkgAcqIndexMergeDiffs() {} // AcqIndex::AcqIndex - Constructor /*{{{*/ pkgAcqIndex::pkgAcqIndex(pkgAcquire * const Owner, @@ -2539,6 +2545,7 @@ void pkgAcqIndex::StageDecompressDone(string const &, return; } /*}}}*/ +pkgAcqIndex::~pkgAcqIndex() {} // AcqArchive::AcqArchive - Constructor /*{{{*/ @@ -2836,6 +2843,7 @@ std::string pkgAcqArchive::ShortDesc() const /*{{{*/ return Desc.ShortDesc; } /*}}}*/ +pkgAcqArchive::~pkgAcqArchive() {} // AcqChangelog::pkgAcqChangelog - Constructors /*{{{*/ pkgAcqChangelog::pkgAcqChangelog(pkgAcquire * const Owner, pkgCache::VerIterator const &Ver, @@ -3156,3 +3164,4 @@ string pkgAcqFile::Custom600Headers() const /*{{{*/ return ""; } /*}}}*/ +pkgAcqFile::~pkgAcqFile() {} diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index 9dbacc1ea..df1380b5e 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -1,6 +1,5 @@ // -*- 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 @@ -345,6 +344,7 @@ class pkgAcquire::Item : public WeakPointable /*{{{*/ class APT_HIDDEN pkgAcqTransactionItem: public pkgAcquire::Item /*{{{*/ /** \brief baseclass for the indexes files to manage them all together */ { + void *d; protected: IndexTarget const Target; HashStringList GetExpectedHashesFor(std::string const MetaKey) const; @@ -380,7 +380,6 @@ class APT_HIDDEN pkgAcqMetaBase : public pkgAcqTransactionItem /*{{{*/ /** \brief the manager of a transaction */ { void *d; - protected: std::vector Transaction; @@ -478,6 +477,7 @@ class APT_HIDDEN pkgAcqMetaBase : public pkgAcqTransactionItem /*{{{*/ std::vector const IndexTargets, IndexTarget const &DataTarget, indexRecords* const MetaIndexParser); + virtual ~pkgAcqMetaBase(); }; /*}}}*/ /** \brief An item that is responsible for downloading the meta-index {{{ @@ -493,7 +493,6 @@ class APT_HIDDEN pkgAcqMetaBase : public pkgAcqTransactionItem /*{{{*/ class APT_HIDDEN pkgAcqMetaIndex : public pkgAcqMetaBase { void *d; - protected: IndexTarget const DetachedSigTarget; @@ -513,6 +512,7 @@ class APT_HIDDEN pkgAcqMetaIndex : public pkgAcqMetaBase pkgAcqMetaIndex(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, IndexTarget const &DataTarget, IndexTarget const &DetachedSigTarget, std::vector const IndexTargets, indexRecords * const MetaIndexParser); + virtual ~pkgAcqMetaIndex(); friend class pkgAcqMetaSig; }; @@ -589,6 +589,7 @@ class APT_HIDDEN pkgAcqBaseIndex : public pkgAcqTransactionItem pkgAcqBaseIndex(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, IndexTarget const Target); + virtual ~pkgAcqBaseIndex(); }; /*}}}*/ /** \brief An item that is responsible for fetching an index file of {{{ @@ -652,6 +653,7 @@ class APT_HIDDEN pkgAcqDiffIndex : public pkgAcqBaseIndex */ pkgAcqDiffIndex(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, IndexTarget const Target); + virtual ~pkgAcqDiffIndex(); private: APT_HIDDEN void QueueOnIMSHit() const; }; @@ -751,6 +753,7 @@ class APT_HIDDEN pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex pkgAcqIndexMergeDiffs(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, IndexTarget const Target, DiffInfo const &patch, std::vector const * const allPatches); + virtual ~pkgAcqIndexMergeDiffs(); }; /*}}}*/ /** \brief An item that is responsible for fetching server-merge patches {{{ @@ -864,6 +867,7 @@ class APT_HIDDEN pkgAcqIndexDiffs : public pkgAcqBaseIndex pkgAcqIndexDiffs(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, IndexTarget const Target, std::vector const &diffs=std::vector()); + virtual ~pkgAcqIndexDiffs(); }; /*}}}*/ /** \brief An acquire item that is responsible for fetching an index {{{ @@ -940,8 +944,10 @@ class APT_HIDDEN pkgAcqIndex : public pkgAcqBaseIndex pkgAcqIndex(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, IndexTarget const Target); + virtual ~pkgAcqIndex(); - void Init(std::string const &URI, std::string const &URIDesc, + private: + APT_HIDDEN void Init(std::string const &URI, std::string const &URIDesc, std::string const &ShortDesc); }; /*}}}*/ @@ -1030,6 +1036,7 @@ class pkgAcqArchive : public pkgAcquire::Item 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 {{{ @@ -1211,6 +1218,7 @@ class pkgAcqFile : public pkgAcquire::Item 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 a8fc75f8e..d3aff4d5e 100644 --- a/apt-pkg/acquire-method.cc +++ b/apt-pkg/acquire-method.cc @@ -478,5 +478,9 @@ void pkgAcqMethod::Dequeue() { /*{{{*/ delete Tmp; } /*}}}*/ - pkgAcqMethod::~pkgAcqMethod() {} + +pkgAcqMethod::FetchItem::FetchItem() {} +pkgAcqMethod::FetchItem::~FetchItem() {} + +pkgAcqMethod::FetchResult::~FetchResult() {} diff --git a/apt-pkg/acquire-method.h b/apt-pkg/acquire-method.h index 6480eb4b5..f6659ef1f 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 *d; }; struct FetchResult @@ -67,6 +71,9 @@ class pkgAcqMethod void TakeHashes(class Hashes &Hash); FetchResult(); + virtual ~FetchResult(); + private: + void *d; }; // State diff --git a/apt-pkg/acquire-worker.h b/apt-pkg/acquire-worker.h index 3a3ef706d..b8e8fefed 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 diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc index 5e5bec95c..75df858a8 100644 --- a/apt-pkg/acquire.cc +++ b/apt-pkg/acquire.cc @@ -1143,6 +1143,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 02031dafd..b7e6c68f1 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 @@ -626,14 +625,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; - } - } + UriIterator(pkgAcquire::Queue *Q); virtual ~UriIterator(); }; /*}}}*/ diff --git a/apt-pkg/algorithms.h b/apt-pkg/algorithms.h index 2ac28c0d7..dab844220 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 *d; protected: class Policy : public pkgDepCache::Policy @@ -88,7 +88,7 @@ private: public: pkgSimulate(pkgDepCache *Cache); - ~pkgSimulate(); + virtual ~pkgSimulate(); }; /*}}}*/ class pkgProblemResolver /*{{{*/ @@ -156,7 +156,7 @@ class pkgProblemResolver /*{{{*/ APT_DEPRECATED void InstallProtect(); pkgProblemResolver(pkgDepCache *Cache); - ~pkgProblemResolver(); + virtual ~pkgProblemResolver(); }; /*}}}*/ bool pkgApplyStatus(pkgDepCache &Cache); diff --git a/apt-pkg/aptconfiguration.h b/apt-pkg/aptconfiguration.h index c7b8d2d73..353843c3e 100644 --- a/apt-pkg/aptconfiguration.h +++ b/apt-pkg/aptconfiguration.h @@ -16,8 +16,7 @@ #include /*}}}*/ 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 static const getCompressionTypes(bool const &Cached = true); + std::vector 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 static const getLanguages(bool const &All = false, + std::vector 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 static const getArchitectures(bool const &Cached = true); + std::vector 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,15 +112,15 @@ public: /*{{{*/ * * \return a vector of Compressors */ - std::vector static const getCompressors(bool const Cached = true); + std::vector const getCompressors(bool const Cached = true); /** \brief Return a vector of extensions supported for data.tar's */ - std::vector static const getCompressorExtensions(); + std::vector const getCompressorExtensions(); /** \return Return a vector of enabled build profile specifications */ - std::vector static const getBuildProfiles(); + std::vector const getBuildProfiles(); /** \return Return a comma-separated list of enabled build profile specifications */ - std::string static const getBuildProfilesString(); + std::string const getBuildProfilesString(); /*}}}*/ }; /*}}}*/ diff --git a/apt-pkg/cachefile.h b/apt-pkg/cachefile.h index 36b20893a..74a092593 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 diff --git a/apt-pkg/cacheset.cc b/apt-pkg/cacheset.cc index 0ad99713a..c42f76112 100644 --- a/apt-pkg/cacheset.cc +++ b/apt-pkg/cacheset.cc @@ -37,7 +37,6 @@ #include /*}}}*/ 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) { @@ -812,4 +811,18 @@ APT_CONST void CacheSetHelper::showSelectedVersion(pkgCache::PkgIterator const & bool const /*verIsRel*/) { } /*}}}*/ + +CacheSetHelper::CacheSetHelper(bool const ShowError, GlobalError::MsgType ErrorType) : + ShowError(ShowError), ErrorType(ErrorType) {} +CacheSetHelper::~CacheSetHelper() {} + +PackageContainerInterface::PackageContainerInterface() : ConstructedBy(CacheSetHelper::UNKNOWN) {} +PackageContainerInterface::PackageContainerInterface(CacheSetHelper::PkgSelector const by) : ConstructedBy(by) {} +PackageContainerInterface::~PackageContainerInterface() {} + +PackageUniverse::PackageUniverse(pkgCache * const Owner) : _cont(Owner) { } +PackageUniverse::~PackageUniverse() {} + +VersionContainerInterface::VersionContainerInterface() {} +VersionContainerInterface::~VersionContainerInterface() {} } diff --git a/apt-pkg/cacheset.h b/apt-pkg/cacheset.h index 97aee8c2d..1a6feb5f7 100644 --- a/apt-pkg/cacheset.h +++ b/apt-pkg/cacheset.h @@ -50,9 +50,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,6 +202,8 @@ 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 *d; }; /*}}}*/ class PackageContainerInterface { /*{{{*/ @@ -263,8 +264,9 @@ 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(); + PackageContainerInterface(CacheSetHelper::PkgSelector const by); + 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 +294,7 @@ APT_IGNORE_DEPRECATED_POP private: CacheSetHelper::PkgSelector ConstructedBy; + void *d; }; /*}}}*/ template class PackageContainer : public PackageContainerInterface {/*{{{*/ @@ -355,7 +358,7 @@ public: /*{{{*/ iterator end() { return iterator(_cont.end()); } const_iterator find(pkgCache::PkgIterator const &P) const { return const_iterator(_cont.find(P)); } - PackageContainer() : PackageContainerInterface() {} + PackageContainer() : PackageContainerInterface(CacheSetHelper::UNKNOWN) {} PackageContainer(CacheSetHelper::PkgSelector const &by) : PackageContainerInterface(by) {} APT_IGNORE_DEPRECATED_PUSH APT_DEPRECATED PackageContainer(Constructor const &by) : PackageContainerInterface((CacheSetHelper::PkgSelector)by) {} @@ -552,6 +555,7 @@ template<> template inline bool PackageContainerPkgBegin(); } APT_PUBLIC iterator end() { return _cont->PkgEnd(); } - APT_PUBLIC PackageUniverse(pkgCache * const Owner) : _cont(Owner) { } + APT_PUBLIC PackageUniverse(pkgCache * const Owner); + APT_PUBLIC virtual ~PackageUniverse(); private: bool insert(pkgCache::PkgIterator const &) { return true; } @@ -701,6 +706,11 @@ APT_IGNORE_DEPRECATED_PUSH } APT_IGNORE_DEPRECATED_POP + VersionContainerInterface(); + virtual ~VersionContainerInterface(); +private: + void *d; + protected: /*{{{*/ /** \brief returns the candidate version of the package diff --git a/apt-pkg/cdrom.cc b/apt-pkg/cdrom.cc index 8cec4b78e..de5cd0657 100644 --- a/apt-pkg/cdrom.cc +++ b/apt-pkg/cdrom.cc @@ -1022,3 +1022,9 @@ pkgUdevCdromDevices::~pkgUdevCdromDevices() /*{{{*/ dlclose(libudev_handle); } /*}}}*/ + +pkgCdromStatus::pkgCdromStatus() : totalSteps(0) {} +pkgCdromStatus::~pkgCdromStatus() {} + +pkgCdrom::pkgCdrom() {} +pkgCdrom::~pkgCdrom() {} diff --git a/apt-pkg/cdrom.h b/apt-pkg/cdrom.h index bd0902176..5626b5059 100644 --- a/apt-pkg/cdrom.h +++ b/apt-pkg/cdrom.h @@ -18,12 +18,13 @@ class OpProgress; class pkgCdromStatus /*{{{*/ { + void *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 *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 *d; protected: // libudev dlopen structure void *libudev_handle; diff --git a/apt-pkg/clean.cc b/apt-pkg/clean.cc index 0fca60ba9..d05ae83b9 100644 --- a/apt-pkg/clean.cc +++ b/apt-pkg/clean.cc @@ -132,4 +132,5 @@ bool pkgArchiveCleaner::Go(std::string Dir,pkgCache &Cache) } /*}}}*/ +pkgArchiveCleaner::pkgArchiveCleaner() {} APT_CONST pkgArchiveCleaner::~pkgArchiveCleaner() {} diff --git a/apt-pkg/clean.h b/apt-pkg/clean.h index 466cb67a9..a1495702b 100644 --- a/apt-pkg/clean.h +++ b/apt-pkg/clean.h @@ -30,6 +30,8 @@ class pkgArchiveCleaner public: bool Go(std::string Dir,pkgCache &Cache); + + pkgArchiveCleaner(); virtual ~pkgArchiveCleaner(); }; diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index 944cbe0bf..0fffa52b0 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -576,3 +576,4 @@ debTranslationsIndex::~debTranslationsIndex() {} debSourcesIndex::~debSourcesIndex() {} debDebPkgFileIndex::~debDebPkgFileIndex() {} +debDscFileIndex::~debDscFileIndex() {} diff --git a/apt-pkg/deb/debindexfile.h b/apt-pkg/deb/debindexfile.h index 6b8c78e5a..6285a9e5c 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 @@ -30,6 +29,7 @@ class pkgCacheGenerator; class APT_HIDDEN debStatusIndex : public pkgIndexFile { + void *d; protected: std::string File; @@ -53,6 +53,7 @@ class APT_HIDDEN debStatusIndex : public pkgIndexFile class APT_HIDDEN debPackagesIndex : public pkgIndexTargetFile { + void *d; public: virtual const Type *GetType() const APT_CONST; @@ -71,6 +72,7 @@ class APT_HIDDEN debPackagesIndex : public pkgIndexTargetFile class APT_HIDDEN debTranslationsIndex : public pkgIndexTargetFile { + void *d; public: virtual const Type *GetType() const APT_CONST; @@ -86,6 +88,7 @@ class APT_HIDDEN debTranslationsIndex : public pkgIndexTargetFile class APT_HIDDEN debSourcesIndex : public pkgIndexTargetFile { + void *d; public: virtual const Type *GetType() const APT_CONST; @@ -145,6 +148,7 @@ class APT_HIDDEN debDebPkgFileIndex : public pkgIndexFile class APT_HIDDEN debDscFileIndex : public pkgIndexFile { private: + void *d; std::string DscFile; public: virtual const Type *GetType() const APT_CONST; @@ -157,7 +161,7 @@ class APT_HIDDEN debDscFileIndex : public pkgIndexFile }; debDscFileIndex(std::string &DscFile); - virtual ~debDscFileIndex() {}; + virtual ~debDscFileIndex(); }; class APT_HIDDEN debDebianSourceDirIndex : public debDscFileIndex diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index b328fcea8..34fc98838 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -459,6 +459,8 @@ pkgCache::RlsFileIterator debReleaseIndex::FindInCache(pkgCache &Cache, bool con } /*}}}*/ +debDebFileMetaIndex::~debDebFileMetaIndex() {} + class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type { protected: diff --git a/apt-pkg/deb/debmetaindex.h b/apt-pkg/deb/debmetaindex.h index b448ecc53..f2706e08a 100644 --- a/apt-pkg/deb/debmetaindex.h +++ b/apt-pkg/deb/debmetaindex.h @@ -75,6 +75,7 @@ class APT_HIDDEN debReleaseIndex : public metaIndex { class APT_HIDDEN debDebFileMetaIndex : public metaIndex { private: + void *d; std::string DebFile; debDebPkgFileIndex *DebIndex; public: @@ -94,7 +95,7 @@ class APT_HIDDEN debDebFileMetaIndex : public metaIndex return true; } debDebFileMetaIndex(std::string const &DebFile); - virtual ~debDebFileMetaIndex() {}; + virtual ~debDebFileMetaIndex(); }; diff --git a/apt-pkg/deb/debrecords.cc b/apt-pkg/deb/debrecords.cc index 335bcfda0..f527042e4 100644 --- a/apt-pkg/deb/debrecords.cc +++ b/apt-pkg/deb/debrecords.cc @@ -51,6 +51,7 @@ bool debRecordParser::Jump(pkgCache::DescFileIterator const &Desc) /*}}}*/ debRecordParser::~debRecordParser() {} +debRecordParserBase::debRecordParserBase() : Parser() {} // RecordParserBase::FileName - Return the archive filename on the site /*{{{*/ string debRecordParserBase::FileName() { @@ -207,3 +208,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(), debFileName(FileName) {} +debDebFileRecordParser::~debDebFileRecordParser() {} diff --git a/apt-pkg/deb/debrecords.h b/apt-pkg/deb/debrecords.h index 38e071940..8efcec8cd 100644 --- a/apt-pkg/deb/debrecords.h +++ b/apt-pkg/deb/debrecords.h @@ -27,6 +27,7 @@ class APT_HIDDEN debRecordParserBase : public pkgRecords::Parser { + void *d; protected: pkgTagSection Section; @@ -50,12 +51,13 @@ class APT_HIDDEN debRecordParserBase : public pkgRecords::Parser virtual void GetRec(const char *&Start,const char *&Stop); - debRecordParserBase() : Parser() {} + debRecordParserBase(); virtual ~debRecordParserBase(); }; class APT_HIDDEN debRecordParser : public debRecordParserBase { + void *d; protected: FileFd File; pkgTagFile Tags; @@ -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 *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 &); + bool Jump(pkgCache::DescFileIterator const &); public: - virtual std::string FileName() { return debFileName; } + virtual std::string FileName(); - 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..21a4ff8ea 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), 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..7aeb2db88 100644 --- a/apt-pkg/deb/debsrcrecords.h +++ b/apt-pkg/deb/debsrcrecords.h @@ -56,9 +56,7 @@ class APT_HIDDEN debSrcRecordParser : public pkgSrcRecords::Parser virtual bool Files(std::vector &F); bool Files2(std::vector &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/debversion.h b/apt-pkg/deb/debversion.h index 434ff4a2e..7befe6372 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 diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h index 20d263c67..94c1088f2 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 *d; pkgDepCache &cache; bool released; @@ -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 @@ -503,6 +503,8 @@ class pkgDepCache : protected pkgCache::Namespace bool const rPurge, unsigned long const Depth, bool const FromUser); private: + void *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 41cc2cdfe..25d53747c 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -39,60 +39,15 @@ 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 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()); @@ -147,8 +102,8 @@ 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; @@ -183,8 +138,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) { @@ -235,6 +190,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 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 +366,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 +391,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 +444,11 @@ bool EDSP::ReadRequest(int const input, std::list &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..72b886a31 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 &install, + bool ReadRequest(int const input, std::list &install, std::list &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 const &install, + bool ApplyRequest(std::list const &install, std::list 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,7 +208,7 @@ 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); }; diff --git a/apt-pkg/edsp/edspindexfile.cc b/apt-pkg/edsp/edspindexfile.cc index a2ec0a19b..5d9383e94 100644 --- a/apt-pkg/edsp/edspindexfile.cc +++ b/apt-pkg/edsp/edspindexfile.cc @@ -81,3 +81,5 @@ const pkgIndexFile::Type *edspIndex::GetType() const return &_apt_Universe; } /*}}}*/ + +edspIndex::~edspIndex() {} diff --git a/apt-pkg/edsp/edspindexfile.h b/apt-pkg/edsp/edspindexfile.h index 8c18d8cbd..0f63b7b2a 100644 --- a/apt-pkg/edsp/edspindexfile.h +++ b/apt-pkg/edsp/edspindexfile.h @@ -30,6 +30,7 @@ class APT_HIDDEN edspIndex : public debStatusIndex virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const; edspIndex(std::string File); + virtual ~edspIndex(); }; #endif diff --git a/apt-pkg/edsp/edsplistparser.cc b/apt-pkg/edsp/edsplistparser.cc index d62abe709..d1c0cf7e8 100644 --- a/apt-pkg/edsp/edsplistparser.cc +++ b/apt-pkg/edsp/edsplistparser.cc @@ -92,3 +92,5 @@ APT_CONST bool edspListParser::LoadReleaseInfo(pkgCache::RlsFileIterator & /*Fil return true; } /*}}}*/ + +edspListParser::~edspListParser() {} diff --git a/apt-pkg/edsp/edsplistparser.h b/apt-pkg/edsp/edsplistparser.h index abe2ef139..ef5179e68 100644 --- a/apt-pkg/edsp/edsplistparser.h +++ b/apt-pkg/edsp/edsplistparser.h @@ -27,6 +27,7 @@ class FileFd; class APT_HIDDEN edspListParser : public debListParser { + void *d; public: virtual bool NewVersion(pkgCache::VerIterator &Ver); virtual std::string Description(); @@ -38,6 +39,7 @@ class APT_HIDDEN edspListParser : public debListParser std::string const §ion); edspListParser(FileFd *File, std::string const &Arch = ""); + virtual ~edspListParser(); protected: virtual bool ParseStatus(pkgCache::PkgIterator &Pkg,pkgCache::VerIterator &Ver); diff --git a/apt-pkg/edsp/edspsystem.h b/apt-pkg/edsp/edspsystem.h index 06a63f40c..1e27d2cb0 100644 --- a/apt-pkg/edsp/edspsystem.h +++ b/apt-pkg/edsp/edspsystem.h @@ -42,7 +42,7 @@ class APT_HIDDEN edspSystem : public pkgSystem pkgIndexFile *&Found) const; edspSystem(); - ~edspSystem(); + virtual ~edspSystem(); }; #endif diff --git a/apt-pkg/indexcopy.cc b/apt-pkg/indexcopy.cc index 461aa4217..120d061ad 100644 --- a/apt-pkg/indexcopy.cc +++ b/apt-pkg/indexcopy.cc @@ -770,4 +770,14 @@ bool TranslationsCopy::CopyTranslations(string CDROM,string Name, /*{{{*/ } /*}}}*/ +IndexCopy::IndexCopy() {} APT_CONST IndexCopy::~IndexCopy() {} + +PackageCopy::PackageCopy() : IndexCopy() {} +APT_CONST PackageCopy::~PackageCopy() {} +SourceCopy::SourceCopy() : IndexCopy() {} +APT_CONST SourceCopy::~SourceCopy() {} +TranslationsCopy::TranslationsCopy() {} +APT_CONST TranslationsCopy::~TranslationsCopy() {} +SigVerify::SigVerify() {} +APT_CONST SigVerify::~SigVerify() {} diff --git a/apt-pkg/indexcopy.h b/apt-pkg/indexcopy.h index 729b0c8cb..7ee162542 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 @@ -54,39 +53,52 @@ class IndexCopy /*{{{*/ bool CopyPackages(std::string CDROM,std::string Name,std::vector &List, pkgCdromStatus *log); + IndexCopy(); virtual ~IndexCopy(); }; /*}}}*/ class PackageCopy : public IndexCopy /*{{{*/ { + void *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";}; - + + public: + PackageCopy(); + virtual ~PackageCopy(); }; /*}}}*/ class SourceCopy : public IndexCopy /*{{{*/ { + void *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";}; - + + public: + SourceCopy(); + virtual ~SourceCopy(); }; /*}}}*/ class TranslationsCopy /*{{{*/ { + void *d; protected: pkgTagSection *Section; public: bool CopyTranslations(std::string CDROM,std::string Name,std::vector &List, pkgCdromStatus *log); + + TranslationsCopy(); + virtual ~TranslationsCopy(); }; /*}}}*/ class SigVerify /*{{{*/ @@ -106,6 +118,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 605bbeb47..b3c5cf229 100644 --- a/apt-pkg/indexfile.cc +++ b/apt-pkg/indexfile.cc @@ -227,3 +227,6 @@ bool pkgIndexTargetFile::Exists() const /*{{{*/ return FileExists(IndexFileName()); } /*}}}*/ + +APT_CONST pkgIndexFile::~pkgIndexFile() {} +APT_CONST pkgIndexTargetFile::~pkgIndexTargetFile() {} diff --git a/apt-pkg/indexfile.h b/apt-pkg/indexfile.h index 042e5c2f7..c51879bb8 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. @@ -90,6 +89,7 @@ class IndexTarget /*{{{*/ class pkgIndexFile { + void *d; protected: bool Trusted; @@ -145,11 +145,12 @@ class pkgIndexFile bool IsTrusted() const { return Trusted; }; pkgIndexFile(bool Trusted); - virtual ~pkgIndexFile() {}; + virtual ~pkgIndexFile(); }; class pkgIndexTargetFile : public pkgIndexFile { + void *d; protected: IndexTarget const Target; @@ -162,6 +163,7 @@ public: virtual unsigned long Size() const; pkgIndexTargetFile(IndexTarget const &Target, bool const Trusted); + virtual ~pkgIndexTargetFile(); }; #endif diff --git a/apt-pkg/indexrecords.h b/apt-pkg/indexrecords.h index 6ed5f0c2b..f7dfa3235 100644 --- a/apt-pkg/indexrecords.h +++ b/apt-pkg/indexrecords.h @@ -1,7 +1,4 @@ // -*- 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 diff --git a/apt-pkg/install-progress.cc b/apt-pkg/install-progress.cc index 5ea8bf4d0..ee2ef683f 100644 --- a/apt-pkg/install-progress.cc +++ b/apt-pkg/install-progress.cc @@ -69,6 +69,7 @@ PackageManagerProgressFd::PackageManagerProgressFd(int progress_fd) { OutStatusFd = progress_fd; } +PackageManagerProgressFd::~PackageManagerProgressFd() {} void PackageManagerProgressFd::WriteToStatusFd(std::string s) { @@ -157,6 +158,7 @@ PackageManagerProgressDeb822Fd::PackageManagerProgressDeb822Fd(int progress_fd) { OutStatusFd = progress_fd; } +PackageManagerProgressDeb822Fd::~PackageManagerProgressDeb822Fd() {} void PackageManagerProgressDeb822Fd::WriteToStatusFd(std::string s) { @@ -433,6 +435,10 @@ bool PackageManagerText::StatusChanged(std::string PackageName, return true; } +PackageManagerText::PackageManagerText() : PackageManager() {} +PackageManagerText::~PackageManagerText() {} + + } // namespace progress diff --git a/apt-pkg/install-progress.h b/apt-pkg/install-progress.h index d8b4a5c82..a4c5daf7f 100644 --- a/apt-pkg/install-progress.h +++ b/apt-pkg/install-progress.h @@ -61,6 +61,7 @@ namespace Progress { class PackageManagerProgressFd : public PackageManager { + void *d; protected: int OutStatusFd; int StepsDone; @@ -69,6 +70,7 @@ namespace Progress { public: PackageManagerProgressFd(int progress_fd); + virtual ~PackageManagerProgressFd(); virtual void StartDpkg(); virtual void Stop(); @@ -90,6 +92,7 @@ namespace Progress { class PackageManagerProgressDeb822Fd : public PackageManager { + void *d; protected: int OutStatusFd; int StepsDone; @@ -98,6 +101,7 @@ namespace Progress { public: PackageManagerProgressDeb822Fd(int progress_fd); + virtual ~PackageManagerProgressDeb822Fd(); virtual void StartDpkg(); virtual void Stop(); @@ -118,6 +122,7 @@ namespace Progress { class PackageManagerFancy : public PackageManager { + void *d; private: APT_HIDDEN static void staticSIGWINCH(int); static std::vector instances; @@ -138,7 +143,7 @@ namespace Progress { public: PackageManagerFancy(); - ~PackageManagerFancy(); + virtual ~PackageManagerFancy(); virtual void Start(int child_pty=-1); virtual void Stop(); virtual bool StatusChanged(std::string PackageName, @@ -153,11 +158,15 @@ namespace Progress { class PackageManagerText : public PackageManager { + void *d; public: virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps, std::string HumanReadableAction); + + PackageManagerText(); + virtual ~PackageManagerText(); }; diff --git a/apt-pkg/metaindex.h b/apt-pkg/metaindex.h index e1810fb27..760c7dd15 100644 --- a/apt-pkg/metaindex.h +++ b/apt-pkg/metaindex.h @@ -28,6 +28,7 @@ class OpProgress; class metaIndex { + void *d; protected: std::vector *Indexes; const char *Type; diff --git a/apt-pkg/orderlist.h b/apt-pkg/orderlist.h index b8bad81b3..29ef79b84 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 *d; protected: pkgDepCache &Cache; @@ -123,7 +123,7 @@ class pkgOrderList : protected pkgCache::Namespace int Score(PkgIterator Pkg); pkgOrderList(pkgDepCache *Cache); - ~pkgOrderList(); + virtual ~pkgOrderList(); }; #endif diff --git a/apt-pkg/packagemanager.h b/apt-pkg/packagemanager.h index fce0ad301..60414ae1c 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 @@ -146,6 +145,7 @@ class pkgPackageManager : protected pkgCache::Namespace virtual ~pkgPackageManager(); private: + void *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 9fe382108..dc7698edd 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -1059,3 +1059,5 @@ bool pkgCache::PrvIterator::IsMultiArchImplicit() const return false; } /*}}}*/ + +pkgCache::~pkgCache() {} diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h index 3cc85f1e8..b7bf26c2a 100644 --- a/apt-pkg/pkgcache.h +++ b/apt-pkg/pkgcache.h @@ -266,11 +266,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 *d; bool MultiArchEnabled; APT_HIDDEN PkgIterator SingleArchFindPkg(const std::string &Name); }; diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index ea0205944..54e2ef19c 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -1720,3 +1720,6 @@ bool pkgCacheGenerator::FinishCache(OpProgress * /*Progress*/) return true; } /*}}}*/ + +pkgCacheGenerator::ListParser::ListParser() : Owner(NULL), OldDepLast(NULL), FoundFileDeps(false) {} +pkgCacheGenerator::ListParser::~ListParser() {} diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h index ade93795b..3c1a40972 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. @@ -123,9 +122,10 @@ class APT_HIDDEN pkgCacheGenerator /*{{{*/ void ReMap(void const * const oldMap, void const * const newMap); pkgCacheGenerator(DynamicMMap *Map,OpProgress *Progress); - ~pkgCacheGenerator(); + virtual ~pkgCacheGenerator(); private: + void *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, @@ -151,7 +151,9 @@ class APT_HIDDEN pkgCacheGenerator::ListParser // Flag file dependencies bool FoundFileDeps; - + + void *d; + protected: inline map_stringitem_t StoreString(pkgCacheGenerator::StringType const type, std::string const &S) {return Owner->StoreString(type, S);}; @@ -182,10 +184,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; @@ -197,8 +196,8 @@ class APT_HIDDEN pkgCacheGenerator::ListParser virtual bool CollectFileProvides(pkgCache &/*Cache*/, pkgCache::VerIterator &/*Ver*/) {return true;}; - ListParser() : Owner(NULL), OldDepLast(NULL), FoundFileDeps(false) {}; - virtual ~ListParser() {}; + ListParser(); + virtual ~ListParser(); }; /*}}}*/ diff --git a/apt-pkg/pkgrecords.cc b/apt-pkg/pkgrecords.cc index 859af3a09..87c965f87 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() {} +pkgRecords::Parser::~Parser() {} diff --git a/apt-pkg/pkgrecords.h b/apt-pkg/pkgrecords.h index bcc05baba..66eb17857 100644 --- a/apt-pkg/pkgrecords.h +++ b/apt-pkg/pkgrecords.h @@ -43,7 +43,7 @@ class pkgRecords /*{{{*/ // Construct destruct pkgRecords(pkgCache &Cache); - ~pkgRecords(); + virtual ~pkgRecords(); }; /*}}}*/ class pkgRecords::Parser /*{{{*/ @@ -106,10 +106,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 *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..98daeb2b9 100644 --- a/apt-pkg/pkgsystem.cc +++ b/apt-pkg/pkgsystem.cc @@ -45,3 +45,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..3a447da8b 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. @@ -93,7 +92,9 @@ class pkgSystem }; pkgSystem(); - virtual ~pkgSystem() {}; + virtual ~pkgSystem(); + private: + void *d; }; // The environment we are operating in. diff --git a/apt-pkg/policy.cc b/apt-pkg/policy.cc index bd40ad2d9..6da6ed606 100644 --- a/apt-pkg/policy.cc +++ b/apt-pkg/policy.cc @@ -439,3 +439,5 @@ bool ReadPinFile(pkgPolicy &Plcy,string File) return true; } /*}}}*/ + +pkgPolicy::~pkgPolicy() {delete [] PFPriority; delete [] Pins;} diff --git a/apt-pkg/policy.h b/apt-pkg/policy.h index f15d8c0a0..c4b1cbadd 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 @@ -85,7 +84,9 @@ class pkgPolicy : public pkgDepCache::Policy bool InitDefaults(); pkgPolicy(pkgCache *Owner); - virtual ~pkgPolicy() {delete [] PFPriority; delete [] Pins;}; + virtual ~pkgPolicy(); + private: + void *d; }; bool ReadPinFile(pkgPolicy &Plcy, std::string File = ""); diff --git a/apt-pkg/sourcelist.h b/apt-pkg/sourcelist.h index 998357509..c92643829 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 @@ -54,6 +53,7 @@ class metaIndex; class pkgSourceList { + void *d; public: // List of supported source list types @@ -118,7 +118,7 @@ class pkgSourceList pkgSourceList(); pkgSourceList(std::string File); - ~pkgSourceList(); + virtual ~pkgSourceList(); }; #endif diff --git a/apt-pkg/srcrecords.h b/apt-pkg/srcrecords.h index c931e17b7..dda66ce48 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 diff --git a/apt-pkg/tagfile.h b/apt-pkg/tagfile.h index 118954541..24eda02f7 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 @@ -47,7 +46,6 @@ class pkgTagSection APT_DEPRECATED unsigned int TagCount; #endif - // dpointer placeholder (for later in case we need it) pkgTagSectionPrivate *d; protected: 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 -- cgit v1.2.3