From 9c5104cf35c6bca91247a8a31c1748be80ab7d68 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Wed, 10 Jul 2013 16:41:14 +0200 Subject: apt-pkg/packagemanager.cc: * apt-pkg/packagemanager.cc: - increate APT::pkgPackageManager::MaxLoopCount to 5000 --- apt-pkg/packagemanager.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc index 310934c42..8c0d2e855 100644 --- a/apt-pkg/packagemanager.cc +++ b/apt-pkg/packagemanager.cc @@ -338,7 +338,7 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) however if there is a loop (A depends on B, B depends on A) this will not be the case, so check for dependencies before configuring. */ bool Bad = false, Changed = false; - const unsigned int max_loops = _config->FindI("APT::pkgPackageManager::MaxLoopCount", 500); + const unsigned int max_loops = _config->FindI("APT::pkgPackageManager::MaxLoopCount", 5000); unsigned int i=0; std::list needConfigure; do @@ -628,7 +628,7 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c This will be either dealt with if the package is configured as a dependency of Pkg (if and when Pkg is configured), or by the ConfigureAll call at the end of the for loop in OrderInstall. */ bool Changed = false; - const unsigned int max_loops = _config->FindI("APT::pkgPackageManager::MaxLoopCount", 500); + const unsigned int max_loops = _config->FindI("APT::pkgPackageManager::MaxLoopCount", 5000); unsigned int i = 0; do { -- cgit v1.2.3 From 7a948ec719ecc020c2337fe3f41c5fc42699e2c1 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 26 Jun 2013 17:37:57 +0200 Subject: Version 3 for DPkg::Pre-Install-Pkgs with MultiArch info Adds on top of Version 2 to all displayed version numbers the architecture as well as the MultiArch flag for consumption by the hooks. Most of the time the architecture will be the same for both versions displayed, but packages might change from "all" to "any" (or back) between versions so we can't display the architecture for packages. Pseudo-Format for Version 3: Examples: stuff - - none < 1 amd64 none **CONFIGURE** libsame 1 i386 same < 2 i386 same **CONFIGURE** stuff 2 i386 none > 1 i386 none **CONFIGURE** libsame 2 i386 same > - - none **REMOVE** toolkit 1 all foreign > - - none **REMOVE** Closes: #712116 --- apt-pkg/cacheiterators.h | 1 + apt-pkg/deb/dpkgpm.cc | 71 ++++++++++++++++++++++++++++++++++-------------- apt-pkg/deb/dpkgpm.h | 4 ++- apt-pkg/pkgcache.cc | 12 ++++++++ 4 files changed, 66 insertions(+), 22 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h index 179a0e963..886d84838 100644 --- a/apt-pkg/cacheiterators.h +++ b/apt-pkg/cacheiterators.h @@ -220,6 +220,7 @@ class pkgCache::VerIterator : public Iterator { inline VerFileIterator FileList() const; bool Downloadable() const; inline const char *PriorityType() const {return Owner->Priority(S->Priority);}; + const char *MultiArchType() const; std::string RelStr() const; bool Automatic() const; diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 3bc31dc37..fb0473535 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -238,15 +238,23 @@ bool pkgDPkgPM::Remove(PkgIterator Pkg,bool Purge) return true; } /*}}}*/ -// DPkgPM::SendV2Pkgs - Send version 2 package info /*{{{*/ +// DPkgPM::SendPkgInfo - Send info for install-pkgs hook /*{{{*/ // --------------------------------------------------------------------- /* This is part of the helper script communication interface, it sends very complete information down to the other end of the pipe.*/ bool pkgDPkgPM::SendV2Pkgs(FILE *F) { - fprintf(F,"VERSION 2\n"); - - /* Write out all of the configuration directives by walking the + return SendPkgsInfo(F, 2); +} +bool pkgDPkgPM::SendPkgsInfo(FILE * const F, unsigned int const &Version) +{ + // This version of APT supports only v3, so don't sent higher versions + if (Version <= 3) + fprintf(F,"VERSION %u\n", Version); + else + fprintf(F,"VERSION 3\n"); + + /* Write out all of the configuration directives by walking the configuration tree */ const Configuration::Item *Top = _config->Tree(0); for (; Top != 0;) @@ -280,30 +288,51 @@ bool pkgDPkgPM::SendV2Pkgs(FILE *F) pkgDepCache::StateCache &S = Cache[I->Pkg]; fprintf(F,"%s ",I->Pkg.Name()); - // Current version - if (I->Pkg->CurrentVer == 0) - fprintf(F,"- "); + + // Current version which we are going to replace + pkgCache::VerIterator CurVer = I->Pkg.CurrentVer(); + if (CurVer.end() == true && (I->Op == Item::Remove || I->Op == Item::Purge)) + CurVer = FindNowVersion(I->Pkg); + + else if (CurVer.end() == true) + { + if (Version <= 2) + fprintf(F, "- "); + else + fprintf(F, "- - none "); + } else - fprintf(F,"%s ",I->Pkg.CurrentVer().VerStr()); - - // Show the compare operator - // Target version + { + fprintf(F, "%s ", CurVer.VerStr()); + if (Version >= 3) + fprintf(F, "%s %s ", CurVer.Arch(), CurVer.MultiArchType()); + } + + // Show the compare operator between current and install version if (S.InstallVer != 0) { + pkgCache::VerIterator const InstVer = S.InstVerIter(Cache); int Comp = 2; - if (I->Pkg->CurrentVer != 0) - Comp = S.InstVerIter(Cache).CompareVer(I->Pkg.CurrentVer()); + if (CurVer.end() == false) + Comp = InstVer.CompareVer(CurVer); if (Comp < 0) fprintf(F,"> "); - if (Comp == 0) + else if (Comp == 0) fprintf(F,"= "); - if (Comp > 0) + else if (Comp > 0) fprintf(F,"< "); - fprintf(F,"%s ",S.InstVerIter(Cache).VerStr()); + fprintf(F, "%s ", InstVer.VerStr()); + if (Version >= 3) + fprintf(F, "%s %s ", InstVer.Arch(), InstVer.MultiArchType()); } else - fprintf(F,"> - "); - + { + if (Version <= 2) + fprintf(F, "> - "); + else + fprintf(F, "> - - none "); + } + // Show the filename/operation if (I->Op == Item::Install) { @@ -313,9 +342,9 @@ bool pkgDPkgPM::SendV2Pkgs(FILE *F) else fprintf(F,"%s\n",I->File.c_str()); } - if (I->Op == Item::Configure) + else if (I->Op == Item::Configure) fprintf(F,"**CONFIGURE**\n"); - if (I->Op == Item::Remove || + else if (I->Op == Item::Remove || I->Op == Item::Purge) fprintf(F,"**REMOVE**\n"); @@ -404,7 +433,7 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf) } } else - SendV2Pkgs(F); + SendPkgsInfo(F, Version); fclose(F); diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h index aab39f633..c31d56f8e 100644 --- a/apt-pkg/deb/dpkgpm.h +++ b/apt-pkg/deb/dpkgpm.h @@ -14,6 +14,7 @@ #include #include #include +#include #ifndef APT_8_CLEANER_HEADERS using std::vector; @@ -79,7 +80,8 @@ class pkgDPkgPM : public pkgPackageManager // Helpers bool RunScriptsWithPkgs(const char *Cnf); - bool SendV2Pkgs(FILE *F); + __deprecated bool SendV2Pkgs(FILE *F); + bool SendPkgsInfo(FILE * const F, unsigned int const &Version); void WriteHistoryTag(std::string const &tag, std::string value); // apport integration diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index d7725563b..52e814c0b 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -924,6 +924,18 @@ string pkgCache::VerIterator::RelStr() const return Res; } /*}}}*/ +// VerIterator::MultiArchType - string representing MultiArch flag /*{{{*/ +const char * pkgCache::VerIterator::MultiArchType() const +{ + if ((S->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same) + return "same"; + else if ((S->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign) + return "foreign"; + else if ((S->MultiArch & pkgCache::Version::Allowed) == pkgCache::Version::Allowed) + return "allowed"; + return "none"; +} + /*}}}*/ // 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 -- cgit v1.2.3 From 3d1be93dc4242df2b93de632715a8aa7dd34f96f Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 28 Jun 2013 20:42:18 +0200 Subject: implement arch+= and arch-= for sources.list Default is to acquire all architectures from APT::Architectures which can be changed by arch=, but this isn't very flexible if you want "mostly" the default as you have to hardcode the architectures then, so arch-= and arch+= can be used to add/remove architectures from the default set. On a machine with 'amd64' and 'i386' configured the lines: deb [arch+=armel] http://example.org/debian wheezy rocks deb [arch-=amd64] http://example.org/debian jessie rocks will result in the download of: wheezy Packages for 'amd64', 'i386' and 'armel' jessie Packages for 'i386' --- apt-pkg/deb/debmetaindex.cc | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 7a88d71e3..7dd5ab2bf 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -373,10 +373,29 @@ class debSLTypeDebian : public pkgSourceList::Type string const &Dist, string const &Section, bool const &IsSrc, map const &Options) const { - map::const_iterator const arch = Options.find("arch"); - vector const Archs = + // parse arch=, arch+= and arch-= settings + map::const_iterator arch = Options.find("arch"); + vector Archs = (arch != Options.end()) ? VectorizeString(arch->second, ',') : APT::Configuration::getArchitectures(); + if ((arch = Options.find("arch+")) != Options.end()) + { + std::vector const plusArch = VectorizeString(arch->second, ','); + for (std::vector::const_iterator plus = plusArch.begin(); plus != plusArch.end(); ++plus) + if (std::find(Archs.begin(), Archs.end(), *plus) == Archs.end()) + Archs.push_back(*plus); + } + if ((arch = Options.find("arch-")) != Options.end()) + { + std::vector const minusArch = VectorizeString(arch->second, ','); + for (std::vector::const_iterator minus = minusArch.begin(); minus != minusArch.end(); ++minus) + { + std::vector::iterator kill = std::find(Archs.begin(), Archs.end(), *minus); + if (kill != Archs.end()) + Archs.erase(kill); + } + } + map::const_iterator const trusted = Options.find("trusted"); for (vector::const_iterator I = List.begin(); -- cgit v1.2.3 From 486d190d3c66bb7271509dc002f8ec9e9eb0166c Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 10 Jul 2013 13:06:05 +0200 Subject: prevent MarkInstall of unsynced Multi-Arch:same siblings Multi-Arch: same packages can be co-installed, but need to have the same version for all installed packages (aka "siblings"). Otherwise the unsynced versions will fight against each other and the auto-install as wel as the problem resolver will later have to decide between holding the packages or to remove one of the siblings (usually a foreign) taking a bunch of packages (like the entire foreign setup) with them. The idea here is now to be more pro-active: MarkInstall will fail for a package if the siblings aren't synced, so we don't allow a situation in which a resolver has to decide if to hold or to remove-upgrade under the assumption that the remove-upgrade decision is always wrong and doesn't deserve to be explored (expect valid out-of-syncs of course). Thats a pretty bold move to take for a library which is used by different solvers so this check is done in IsInstallOk and can be overridden if front-ends want to. --- apt-pkg/depcache.cc | 53 +++++++++++++++++++++++++++++++++++++++++++++++++---- apt-pkg/depcache.h | 30 +++++++++++++++++------------- 2 files changed, 66 insertions(+), 17 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 9f8422fec..2c6eb43bf 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -864,6 +864,11 @@ bool pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge, dpkg holds are enforced by the private IsModeChangeOk */ bool pkgDepCache::IsDeleteOk(PkgIterator const &Pkg,bool rPurge, unsigned long Depth, bool FromUser) +{ + return IsDeleteOkProtectInstallRequests(Pkg, rPurge, Depth, FromUser); +} +bool pkgDepCache::IsDeleteOkProtectInstallRequests(PkgIterator const &Pkg, + bool const rPurge, unsigned long const Depth, bool const FromUser) { if (FromUser == false && Pkg->CurrentVer == 0) { @@ -1047,9 +1052,10 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, return true; } - // check if we are allowed to install the package - if (IsInstallOk(Pkg,AutoInst,Depth,FromUser) == false) - return false; + // check if we are allowed to install the package (if we haven't already) + if (P.Mode != ModeInstall || P.InstallVer != P.CandidateVer) + if (IsInstallOk(Pkg,AutoInst,Depth,FromUser) == false) + return false; ActionGroup group(*this); P.iFlags &= ~AutoKept; @@ -1271,11 +1277,50 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, /*}}}*/ // DepCache::IsInstallOk - check if it is ok to install this package /*{{{*/ // --------------------------------------------------------------------- -/* The default implementation does nothing. +/* The default implementation checks if the installation of an M-A:same + package would lead us into a version-screw and if so forbids it. dpkg holds are enforced by the private IsModeChangeOk */ bool pkgDepCache::IsInstallOk(PkgIterator const &Pkg,bool AutoInst, unsigned long Depth, bool FromUser) { + return IsInstallOkMultiArchSameVersionSynced(Pkg,AutoInst, Depth, FromUser); +} +bool pkgDepCache::IsInstallOkMultiArchSameVersionSynced(PkgIterator const &Pkg, + bool const AutoInst, unsigned long const Depth, bool const FromUser) +{ + if (FromUser == true) // as always: user is always right + return true; + + // ignore packages with none-M-A:same candidates + VerIterator const CandVer = PkgState[Pkg->ID].CandidateVerIter(*this); + if (unlikely(CandVer.end() == true) || CandVer == Pkg.CurrentVer() || + (CandVer->MultiArch & pkgCache::Version::Same) != pkgCache::Version::Same) + return true; + + 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 + // (simple string-compare as stuff like '1' == '0:1-0' can't happen here) + if (P->CurrentVer == 0 || strcmp(Pkg.CandVersion(), P.CandVersion()) == 0) + continue; + // packages loosing 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) + continue; + + // not downloadable means the package is obsolete, so allow out-of-sync + if (CV.Downloadable() == false) + continue; + + 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; + return false; + } + return true; } /*}}}*/ diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h index 7358048ed..d9c95349b 100644 --- a/apt-pkg/depcache.h +++ b/apt-pkg/depcache.h @@ -442,16 +442,15 @@ class pkgDepCache : protected pkgCache::Namespace /** \return \b true if it's OK for MarkInstall to install * the given package. * - * See the default implementation for a simple example how this - * method can be used. - * Overriding implementations should use the hold-state-flag to cache - * results from previous checks of this package - also it should - * be used if the default resolver implementation is also used to - * ensure that these packages are handled like "normal" dpkg holds. + * The default implementation simply calls all IsInstallOk* + * method mentioned below. + * + * Overriding implementations should use the hold-state-flag to + * cache results from previous checks of this package - if possible. * * The parameters are the same as in the calling MarkInstall: * \param Pkg the package that MarkInstall wants to install. - * \param AutoInst needs a previous MarkInstall this package? + * \param AutoInst install this and all its dependencies * \param Depth recursive deep of this Marker call * \param FromUser was the install requested by the user? */ @@ -461,12 +460,8 @@ class pkgDepCache : protected pkgCache::Namespace /** \return \b true if it's OK for MarkDelete to remove * the given package. * - * See the default implementation for a simple example how this - * method can be used. - * Overriding implementations should use the hold-state-flag to cache - * results from previous checks of this package - also it should - * be used if the default resolver implementation is also used to - * ensure that these packages are handled like "normal" dpkg holds. + * The default implementation simply calls all IsDeleteOk* + * method mentioned below, see also #IsInstallOk. * * The parameters are the same as in the calling MarkDelete: * \param Pkg the package that MarkDelete wants to remove. @@ -498,6 +493,15 @@ class pkgDepCache : protected pkgCache::Namespace pkgDepCache(pkgCache *Cache,Policy *Plcy = 0); virtual ~pkgDepCache(); + protected: + // methods call by IsInstallOk + bool IsInstallOkMultiArchSameVersionSynced(PkgIterator const &Pkg, + bool const AutoInst, unsigned long const Depth, bool const FromUser); + + // methods call by IsDeleteOk + bool IsDeleteOkProtectInstallRequests(PkgIterator const &Pkg, + bool const rPurge, unsigned long const Depth, bool const FromUser); + private: bool IsModeChangeOk(ModeList const mode, PkgIterator const &Pkg, unsigned long const Depth, bool const FromUser); -- cgit v1.2.3 From 7546c8da99ade7b6e1bd6aaa9d026f61400214d1 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 11 Jul 2013 23:09:47 +0200 Subject: Add DPkgPM::Progress for terminal install progress --- apt-pkg/deb/dpkgpm.cc | 17 ++++++++++++++++- apt-pkg/deb/dpkgpm.h | 2 ++ 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index fb0473535..3fb80d158 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -620,6 +620,9 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) << ":" << (PackagesDone/float(PackagesTotal)*100.0) << ":" << s << endl; + if(_config->FindB("DPkgPM::Progress", false) == true) + SendTerminalProgress(PackagesDone/float(PackagesTotal)*100.0); + if(OutStatusFd > 0) FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); if (Debug == true) @@ -860,6 +863,18 @@ bool pkgDPkgPM::CloseLog() return true; } /*}}}*/ +// DPkgPM::SendTerminalProgress /*{{{*/ +// --------------------------------------------------------------------- +/* Send progress info to the terminal + */ +void pkgDPkgPM::SendTerminalProgress(float percentage) +{ + // FIXME: use colors too + std::cout << "\r\n" + << "Progress: [" << percentage << "%]" + << "\r\n"; +} + /*}}}*/ /*{{{*/ // This implements a racy version of pselect for those architectures // that don't have a working implementation. @@ -1274,7 +1289,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); } Child = ExecFork(); - + // This is the child if (Child == 0) { diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h index c31d56f8e..29901a204 100644 --- a/apt-pkg/deb/dpkgpm.h +++ b/apt-pkg/deb/dpkgpm.h @@ -84,6 +84,8 @@ class pkgDPkgPM : public pkgPackageManager bool SendPkgsInfo(FILE * const F, unsigned int const &Version); void WriteHistoryTag(std::string const &tag, std::string value); + void SendTerminalProgress(float percentage); + // apport integration void WriteApportReport(const char *pkgpath, const char *errormsg); -- cgit v1.2.3 From 86fdeec2a76f6b134ee8400eb1e53d06fe0974fe Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 16 Jul 2013 23:15:55 +0200 Subject: fix if-clause to generate hook-info for 'rc' packages The code incorrectly skips printing of current version information, if the package has no current version (for APT, but for dpkg as it is the case for packages which are removed but not purged) by using an unintended "else if" rather than an "if". Closes: 717006 --- apt-pkg/deb/dpkgpm.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index fb0473535..d8fc8ef68 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -294,7 +294,7 @@ bool pkgDPkgPM::SendPkgsInfo(FILE * const F, unsigned int const &Version) if (CurVer.end() == true && (I->Op == Item::Remove || I->Op == Item::Purge)) CurVer = FindNowVersion(I->Pkg); - else if (CurVer.end() == true) + if (CurVer.end() == true) { if (Version <= 2) fprintf(F, "- "); -- cgit v1.2.3 From 267275c59cc35704789a228c6e9b1464c4cabd74 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 23 Jul 2013 15:00:53 +0200 Subject: remove double list include --- apt-pkg/cacheset.h | 1 - 1 file changed, 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/cacheset.h b/apt-pkg/cacheset.h index 2a45910ba..d7328d705 100644 --- a/apt-pkg/cacheset.h +++ b/apt-pkg/cacheset.h @@ -11,7 +11,6 @@ // Include Files /*{{{*/ #include #include -#include #include #include #include -- cgit v1.2.3 From 96ab3c6f62becde2fc67b81c65eef2881856fd22 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 25 Jul 2013 20:14:31 +0200 Subject: always "delete d" in FileFd::~FileFd to coverity happy --- apt-pkg/contrib/fileutl.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 0f88923cf..edf612810 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -1218,11 +1218,9 @@ FileFd::~FileFd() { Close(); if (d != NULL) - { d->CloseDown(FileName); - delete d; - d = NULL; - } + delete d; + d = NULL; } /*}}}*/ // FileFd::Read - Read a bit of the file /*{{{*/ -- cgit v1.2.3 From 26d5b68a008cfedec113ebdde782c3d18478a5b4 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 25 Jul 2013 20:14:59 +0200 Subject: fix off-by-one error and do not use magic constant of 100 when checking StackPost --- apt-pkg/contrib/configuration.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/configuration.cc b/apt-pkg/contrib/configuration.cc index 808a708a1..376617401 100644 --- a/apt-pkg/contrib/configuration.cc +++ b/apt-pkg/contrib/configuration.cc @@ -811,7 +811,7 @@ bool ReadConfigFile(Configuration &Conf,const string &FName,bool const &AsSectio // Go down a level if (TermChar == '{') { - if (StackPos <= 100) + if (StackPos < sizeof(Stack)/sizeof(std::string)) Stack[StackPos++] = ParentTag; /* Make sectional tags incorperate the section into the -- cgit v1.2.3 From fe0036dd7e3bbd808fa526e2e142fdb89105caae Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 25 Jul 2013 20:22:43 +0200 Subject: rework the code in cdromutl.cc to make coverity (more) happy --- apt-pkg/contrib/cdromutl.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/cdromutl.cc b/apt-pkg/contrib/cdromutl.cc index 187f6bd59..afa01a562 100644 --- a/apt-pkg/contrib/cdromutl.cc +++ b/apt-pkg/contrib/cdromutl.cc @@ -122,8 +122,9 @@ bool MountCdrom(string Path, string DeviceName) if (Child == 0) { // Make all the fds /dev/null + int null_fd = open("/dev/null",O_RDWR); for (int I = 0; I != 3; I++) - dup2(open("/dev/null",O_RDWR),I); + dup2(null_fd, I); if (_config->Exists("Acquire::cdrom::"+Path+"::Mount") == true) { -- cgit v1.2.3 From 3d165906327828990bec2c58a3c1f4ee77467523 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 25 Jul 2013 20:26:11 +0200 Subject: fix resource leak (thanks coverity) --- apt-pkg/contrib/fileutl.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index edf612810..398830ff5 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -244,17 +244,21 @@ int GetLock(string File,bool Errors) fl.l_len = 0; if (fcntl(FD,F_SETLK,&fl) == -1) { + // always close to not leak resources + int Tmp = errno; + close(FD); + errno = Tmp; + if (errno == ENOLCK) { + _error->Warning(_("Not using locking for nfs mounted lock file %s"),File.c_str()); return dup(0); // Need something for the caller to close - } + } + if (Errors == true) _error->Errno("open",_("Could not get lock %s"),File.c_str()); - int Tmp = errno; - close(FD); - errno = Tmp; return -1; } -- cgit v1.2.3 From a80a03448fe11f8ea3fd4a8c525fc413c9ce9037 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 25 Jul 2013 20:36:23 +0200 Subject: call fdopen() after FileFd was checked --- apt-pkg/indexcopy.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/indexcopy.cc b/apt-pkg/indexcopy.cc index 1d61b974d..a2adb2d00 100644 --- a/apt-pkg/indexcopy.cc +++ b/apt-pkg/indexcopy.cc @@ -714,9 +714,9 @@ bool TranslationsCopy::CopyTranslations(string CDROM,string Name, /*{{{*/ } else { Target.Open(TargetF,FileFd::WriteAtomic); } - FILE *TargetFl = fdopen(dup(Target.Fd()),"w"); if (_error->PendingError() == true) return false; + FILE *TargetFl = fdopen(dup(Target.Fd()),"w"); if (TargetFl == 0) return _error->Errno("fdopen","Failed to reopen fd"); -- cgit v1.2.3 From 60fc4f21783fddaae481494f99ec157e08a9bfdb Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 25 Jul 2013 20:41:03 +0200 Subject: apt-pkg/indexcopy.cc: check for pending errors before calling fdopen() --- apt-pkg/indexcopy.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/indexcopy.cc b/apt-pkg/indexcopy.cc index a2adb2d00..4920efff8 100644 --- a/apt-pkg/indexcopy.cc +++ b/apt-pkg/indexcopy.cc @@ -106,9 +106,9 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector &List, } else { Target.Open(TargetF,FileFd::WriteAtomic); } - FILE *TargetFl = fdopen(dup(Target.Fd()),"w"); if (_error->PendingError() == true) return false; + FILE *TargetFl = fdopen(dup(Target.Fd()),"w"); if (TargetFl == 0) return _error->Errno("fdopen","Failed to reopen fd"); -- cgit v1.2.3 From a9d6b0ad873fdf38e7a7077fd1f07289ad66d45a Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 25 Jul 2013 20:45:53 +0200 Subject: fix resource leak when verification fails --- apt-pkg/indexcopy.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'apt-pkg') diff --git a/apt-pkg/indexcopy.cc b/apt-pkg/indexcopy.cc index 4920efff8..7694cb1dd 100644 --- a/apt-pkg/indexcopy.cc +++ b/apt-pkg/indexcopy.cc @@ -601,6 +601,7 @@ bool SigVerify::CopyAndVerify(string CDROM,string Name,vector &SigList, (useInRelease ? inrelease.c_str() : releasegpg.c_str())); // something went wrong, don't copy the Release.gpg // FIXME: delete any existing gpg file? + delete MetaIndex; continue; } -- cgit v1.2.3 From 6612c86ef3d8f2b8bccc6212791996ab9e053082 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 25 Jul 2013 20:46:08 +0200 Subject: delete targets data --- apt-pkg/deb/debmetaindex.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 7dd5ab2bf..b597b6f3c 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -238,6 +238,7 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description, (*Target)->ShortDesc, HashString()); } + delete targets; // this is normally created in pkgAcqMetaSig, but if we run // in --print-uris mode, we add it here -- cgit v1.2.3 From 1b7bf822ad9504f6d01cd4422d830e8815143912 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 25 Jul 2013 20:55:18 +0200 Subject: add missing "free(buffer) for allocated buffer --- apt-pkg/contrib/fileutl.cc | 1 - 1 file changed, 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 398830ff5..0b6e07f75 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -251,7 +251,6 @@ int GetLock(string File,bool Errors) if (errno == ENOLCK) { - _error->Warning(_("Not using locking for nfs mounted lock file %s"),File.c_str()); return dup(0); // Need something for the caller to close } -- cgit v1.2.3 From a5b9f4890fc2b367b8f89d10ea2bdb88b8aa071a Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 25 Jul 2013 18:51:16 +0200 Subject: pick up Translation-* even if only compressed available On CD-ROMs Translation-* files are only in compressed form included in the Release file. This used to work while we had no record of Translation-* files in the Release file at all as APT would have just guessed the (compressed) filename and accepted it (unchecked), but now that it checks for the presents of entries and if it finds records it expects the uncompressed to be verifiable. This commit relaxes this requirement again to fix the regression. We are still secure "enough" as we can validate the compressed file we have downloaded, so we don't loose anything by not requiring a hashsum for the uncompressed files to double-check them. Closes: 717665 --- apt-pkg/acquire-item.cc | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index c48443eff..7bcdf285b 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -1369,9 +1369,20 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify) /*{{{*/ { HashString ExpectedIndexHash; const indexRecords::checkSum *Record = MetaIndexParser->Lookup((*Target)->MetaKey); + bool compressedAvailable = false; if (Record == NULL) { - if (verify == true && (*Target)->IsOptional() == false) + if ((*Target)->IsOptional() == true) + { + std::vector types = APT::Configuration::getCompressionTypes(); + for (std::vector::const_iterator t = types.begin(); t != types.end(); ++t) + if (MetaIndexParser->Exists(string((*Target)->MetaKey).append(".").append(*t)) == true) + { + compressedAvailable = true; + break; + } + } + else if (verify == true) { Status = StatAuthError; strprintf(ErrorText, _("Unable to find expected entry '%s' in Release file (Wrong sources.list entry or malformed file)"), (*Target)->MetaKey.c_str()); @@ -1400,7 +1411,7 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify) /*{{{*/ if ((*Target)->IsSubIndex() == true) new pkgAcqSubIndex(Owner, (*Target)->URI, (*Target)->Description, (*Target)->ShortDesc, ExpectedIndexHash); - else if (transInRelease == false || MetaIndexParser->Exists((*Target)->MetaKey) == true) + else if (transInRelease == false || Record != NULL || compressedAvailable == true) { if (_config->FindB("Acquire::PDiffs",true) == true && transInRelease == true && MetaIndexParser->Exists(string((*Target)->MetaKey).append(".diff/Index")) == true) -- cgit v1.2.3 From 9ca0d58180366275f5e62b6c5aad066b7b09a1de Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 26 Jul 2013 12:04:55 +0200 Subject: proper cleanup varargs in _error (uncovered by Coverity) Git-Dch: Ignore --- apt-pkg/contrib/error.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/error.cc b/apt-pkg/contrib/error.cc index 122e2c809..d457781c3 100644 --- a/apt-pkg/contrib/error.cc +++ b/apt-pkg/contrib/error.cc @@ -67,9 +67,10 @@ bool GlobalError::NAME (const char *Function, const char *Description,...) { \ int const errsv = errno; \ while (true) { \ va_start(args,Description); \ - if (InsertErrno(TYPE, Function, Description, args, errsv, msgSize) == false) \ - break; \ + bool const retry = InsertErrno(TYPE, Function, Description, args, errsv, msgSize); \ va_end(args); \ + if (retry == false) \ + break; \ } \ return false; \ } @@ -88,9 +89,10 @@ bool GlobalError::InsertErrno(MsgType const &type, const char *Function, int const errsv = errno; while (true) { va_start(args,Description); - if (InsertErrno(type, Function, Description, args, errsv, msgSize) == false) - break; + bool const retry = InsertErrno(type, Function, Description, args, errsv, msgSize); va_end(args); + if (retry == false) + break; } return false; } -- cgit v1.2.3 From 638593bd058fc0c715a76de92ff5bd6691c101e4 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 26 Jul 2013 12:20:50 +0200 Subject: ensure that FileFd::Size returns 0 in error cases --- apt-pkg/contrib/fileutl.cc | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 0f88923cf..5debb4f92 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -1598,7 +1598,11 @@ unsigned long long FileFd::Size() char ignore[1000]; unsigned long long read = 0; do { - Read(ignore, sizeof(ignore), &read); + if (Read(ignore, sizeof(ignore), &read) == false) + { + Seek(oldSeek); + return 0; + } } while(read != 0); size = Tell(); Seek(oldSeek); @@ -1615,10 +1619,16 @@ unsigned long long FileFd::Size() * bits of the file */ // FIXME: Size for gz-files is limited by 32bit… no largefile support if (lseek(iFd, -4, SEEK_END) < 0) - return FileFdErrno("lseek","Unable to seek to end of gzipped file"); - size = 0L; + { + FileFdErrno("lseek","Unable to seek to end of gzipped file"); + return 0; + } + size = 0; if (read(iFd, &size, 4) != 4) - return FileFdErrno("read","Unable to read original size of gzipped file"); + { + FileFdErrno("read","Unable to read original size of gzipped file"); + return 0; + } #ifdef WORDS_BIGENDIAN uint32_t tmp_size = size; @@ -1628,7 +1638,10 @@ unsigned long long FileFd::Size() #endif if (lseek(iFd, oldPos, SEEK_SET) < 0) - return FileFdErrno("lseek","Unable to seek in gzipped file"); + { + FileFdErrno("lseek","Unable to seek in gzipped file"); + return 0; + } return size; } -- cgit v1.2.3 From 36a0c0f78675d10cae840a72268f70aed667fb96 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 26 Jul 2013 22:10:05 +0200 Subject: fix some coverity chroot() releated warnings --- apt-pkg/aptconfiguration.cc | 4 ++-- apt-pkg/deb/dpkgpm.cc | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/aptconfiguration.cc b/apt-pkg/aptconfiguration.cc index 37c846582..e32e553a4 100644 --- a/apt-pkg/aptconfiguration.cc +++ b/apt-pkg/aptconfiguration.cc @@ -388,12 +388,12 @@ std::vector const Configuration::getArchitectures(bool const &Cache if (dpkgMultiArch == 0) { close(external[0]); std::string const chrootDir = _config->FindDir("DPkg::Chroot-Directory"); - if (chrootDir != "/" && chroot(chrootDir.c_str()) != 0) - _error->WarningE("getArchitecture", "Couldn't chroot into %s for dpkg --print-foreign-architectures", chrootDir.c_str()); int const nullfd = open("/dev/null", O_RDONLY); dup2(nullfd, STDIN_FILENO); dup2(external[1], STDOUT_FILENO); dup2(nullfd, STDERR_FILENO); + if (chrootDir != "/" && chroot(chrootDir.c_str()) != 0) + _error->WarningE("getArchitecture", "Couldn't chroot into %s for dpkg --print-foreign-architectures", chrootDir.c_str()); execvp(Args[0], (char**) &Args[0]); _error->WarningE("getArchitecture", "Can't detect foreign architectures supported by dpkg!"); _exit(100); diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index fb0473535..588ab68c4 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -134,6 +134,7 @@ static void dpkgChrootDirectory() std::cerr << "Chrooting into " << chrootDir << std::endl; if (chroot(chrootDir.c_str()) != 0) _exit(100); + chdir("/"); } /*}}}*/ -- cgit v1.2.3 From 163dc55bd6891008adcdf6d683a94e890a00f8c7 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 26 Jul 2013 22:18:36 +0200 Subject: fix another missing va_end() --- apt-pkg/contrib/strutl.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index d0e74d8c5..df02c3499 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -1233,12 +1233,12 @@ char *safe_snprintf(char *Buffer,char *End,const char *Format,...) va_list args; int Did; - va_start(args,Format); - if (End <= Buffer) return End; - + va_start(args,Format); Did = vsnprintf(Buffer,End - Buffer,Format,args); + va_end(args); + if (Did < 0 || Buffer + Did > End) return End; return Buffer + Did; -- cgit v1.2.3 From 096bd9f59750f6bea754d3a05e240c9eea0f6b53 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Thu, 1 Aug 2013 13:19:43 +0200 Subject: prefer native arch over higher priority for providers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The rational from the buglog: > The problem here is that the Priority field in one of the Packages files > is incorrect due to a mishap with reprepro configuration, […] the > amd64 version is Priority: standard but the arm64 version is Priority: > optional (and has a stray "optional: interpreters" field). > […] > However, Priority is a rather weak property of a package because it's > typically applied via overrides, and it's easy for maintainers of > third-party repositories to misconfigure them so that overrides aren't > applied correctly. It shouldn't be ranked ahead of choosing packages > from the native architecture. In this case, I have no user-mode > emulation for arm64 set up, so choosing m4:arm64 simply won't work. This effectly makes the priority the least interesting data point in chosing a provider, which is in line with the other checks we have already order above priority in the past and also has a certain appeal by the soft irony it provides. Closes: #718482 --- apt-pkg/depcache.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 2c6eb43bf..978a893f7 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -1007,9 +1007,6 @@ struct CompareProviders { else if ((B->Flags & pkgCache::Flag::Important) == pkgCache::Flag::Important) return true; } - // higher priority seems like a good idea - if (AV->Priority != BV->Priority) - return AV->Priority > BV->Priority; // prefer native architecture if (strcmp(A.Arch(), B.Arch()) != 0) { @@ -1024,6 +1021,9 @@ struct CompareProviders { else if (*a == B.Arch()) return true; } + // higher priority seems like a good idea + if (AV->Priority != BV->Priority) + return AV->Priority > BV->Priority; // unable to decide… return A->ID < B->ID; } -- cgit v1.2.3 From 4ccd3b3ce69d6a6598e1773689a44fdec78a85cc Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 5 Aug 2013 22:40:28 +0200 Subject: fix some unitialized data members --- apt-pkg/cdrom.h | 2 +- apt-pkg/contrib/sha2.h | 4 +++- apt-pkg/tagfile.h | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/cdrom.h b/apt-pkg/cdrom.h index 4fc3d3928..7d19eb813 100644 --- a/apt-pkg/cdrom.h +++ b/apt-pkg/cdrom.h @@ -18,7 +18,7 @@ class pkgCdromStatus /*{{{*/ int totalSteps; public: - pkgCdromStatus() {}; + pkgCdromStatus() : totalSteps(0) {}; virtual ~pkgCdromStatus() {}; // total steps diff --git a/apt-pkg/contrib/sha2.h b/apt-pkg/contrib/sha2.h index 51c921dbd..8e0c99a1b 100644 --- a/apt-pkg/contrib/sha2.h +++ b/apt-pkg/contrib/sha2.h @@ -60,10 +60,11 @@ class SHA256Summation : public SHA2SummationBase res.Set(Sum); return res; }; - SHA256Summation() + SHA256Summation() { SHA256_Init(&ctx); Done = false; + memset(&Sum, 0, sizeof(Sum)); }; }; @@ -96,6 +97,7 @@ class SHA512Summation : public SHA2SummationBase { SHA512_Init(&ctx); Done = false; + memset(&Sum, 0, sizeof(Sum)); }; }; diff --git a/apt-pkg/tagfile.h b/apt-pkg/tagfile.h index 4718f5101..126f4219d 100644 --- a/apt-pkg/tagfile.h +++ b/apt-pkg/tagfile.h @@ -84,7 +84,7 @@ class pkgTagSection Stop = this->Stop; }; - pkgTagSection() : Section(0), TagCount(0), Stop(0) {}; + pkgTagSection() : Section(0), TagCount(0), Stop(0), d(NULL) {}; virtual ~pkgTagSection() {}; }; -- cgit v1.2.3 From b40394c0ff509954c37254b0993a985ea3ff1467 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 6 Aug 2013 09:13:27 +0200 Subject: memset() pkgTagSections data to make coverity happy --- apt-pkg/tagfile.cc | 10 ++++++++++ apt-pkg/tagfile.h | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc index 1c79ee74f..83c1a9a55 100644 --- a/apt-pkg/tagfile.cc +++ b/apt-pkg/tagfile.cc @@ -218,6 +218,16 @@ bool pkgTagFile::Jump(pkgTagSection &Tag,unsigned long long Offset) return true; } /*}}}*/ +// pkgTagSection::pkgTagSection - Constructor /*{{{*/ +// --------------------------------------------------------------------- +/* */ +pkgTagSection::pkgTagSection() + : Section(0), TagCount(0), Stop(0), d(NULL) +{ + memset(&Indexes, 0, sizeof(Indexes)); + memset(&AlphaIndexes, 0, sizeof(AlphaIndexes)); +} + /*}}}*/ // TagSection::Scan - Scan for the end of the header information /*{{{*/ // --------------------------------------------------------------------- /* This looks for the first double new line in the data stream. diff --git a/apt-pkg/tagfile.h b/apt-pkg/tagfile.h index 126f4219d..7b496ffd8 100644 --- a/apt-pkg/tagfile.h +++ b/apt-pkg/tagfile.h @@ -84,7 +84,7 @@ class pkgTagSection Stop = this->Stop; }; - pkgTagSection() : Section(0), TagCount(0), Stop(0), d(NULL) {}; + pkgTagSection(); virtual ~pkgTagSection() {}; }; -- cgit v1.2.3 From 1680800209dc85387c4c2da9a1edfcde44f87807 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 7 Aug 2013 18:00:07 +0200 Subject: specific pins below 1000 cause downgrades MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We start your quest by using the version of a package applying to a specific pin, but that version could very well be below the current version, which causes APT to suggest a downgrade even if it is advertised that it never does this below 1000. Its of course questionable what use a specific pin on a package has which has a newer version already installed, but reacting with the suggestion of a downgrade is really not appropriated (even if its kinda likely that this is actually the intend the user has – it could just as well be an outdated pin) and as pinning is complicated enough we should atleast do what is described in the manpage. So we look out for the specific pin and if we haven't seen it at the moment we see the installed version, we ignore the specific pin. Closes: 543966 --- apt-pkg/policy.cc | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/policy.cc b/apt-pkg/policy.cc index 4ae3b5f87..0a06cc6e3 100644 --- a/apt-pkg/policy.cc +++ b/apt-pkg/policy.cc @@ -166,11 +166,15 @@ pkgCache::VerIterator pkgPolicy::GetCandidateVer(pkgCache::PkgIterator const &Pk tracks the default when the default is taken away, and a permanent pin that stays at that setting. */ + bool PrefSeen = false; for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver) { /* Lets see if this version is the installed version */ bool instVer = (Pkg.CurrentVer() == Ver); + if (Pref == Ver) + PrefSeen = true; + for (pkgCache::VerFileIterator VF = Ver.FileList(); VF.end() == false; ++VF) { /* If this is the status file, and the current version is not the @@ -187,26 +191,33 @@ pkgCache::VerIterator pkgPolicy::GetCandidateVer(pkgCache::PkgIterator const &Pk { Pref = Ver; Max = Prio; + PrefSeen = true; } if (Prio > MaxAlt) { PrefAlt = Ver; MaxAlt = Prio; - } - } - + } + } + if (instVer == true && Max < 1000) { + /* Not having seen the Pref yet means we have a specific pin below 1000 + on a version below the current installed one, so ignore the specific pin + as this would be a downgrade otherwise */ + if (PrefSeen == false || Pref.end() == true) + { + Pref = Ver; + PrefSeen = true; + } /* Elevate our current selection (or the status file itself) to the Pseudo-status priority. */ - if (Pref.end() == true) - Pref = Ver; Max = 1000; - + // Fast path optimize. if (StatusOverride == false) break; - } + } } // If we do not find our candidate, use the one with the highest pin. // This means that if there is a version available with pin > 0; there -- cgit v1.2.3 From 91c4cc14d3654636edf997d23852f05ad3de4853 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 7 Aug 2013 16:40:39 +0200 Subject: stop skipping "-----" sections in Release files The file we read will always be a Release file as the clearsign is stripped earlier in this method, so this check is just wasting CPU Its also removing the risk that this could ever be part of a valid section, even if I can't imagine how that should be valid. Git-Dch: Ignore --- apt-pkg/indexrecords.cc | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/indexrecords.cc b/apt-pkg/indexrecords.cc index e37a78cfb..6d89949a0 100644 --- a/apt-pkg/indexrecords.cc +++ b/apt-pkg/indexrecords.cc @@ -62,7 +62,7 @@ bool indexRecords::Load(const string Filename) /*{{{*/ if (OpenMaybeClearSignedFile(Filename, Fd) == false) return false; - pkgTagFile TagFile(&Fd, Fd.Size() + 256); // XXX + pkgTagFile TagFile(&Fd); if (_error->PendingError() == true) { strprintf(ErrorText, _("Unable to parse Release file %s"),Filename.c_str()); @@ -71,16 +71,11 @@ bool indexRecords::Load(const string Filename) /*{{{*/ pkgTagSection Section; const char *Start, *End; - // Skip over sections beginning with ----- as this is an idicator for clearsigns - do { - if (TagFile.Step(Section) == false) - { - strprintf(ErrorText, _("No sections in Release file %s"), Filename.c_str()); - return false; - } - - Section.Get (Start, End, 0); - } while (End - Start > 5 && strncmp(Start, "-----", 5) == 0); + if (TagFile.Step(Section) == false) + { + strprintf(ErrorText, _("No sections in Release file %s"), Filename.c_str()); + return false; + } Suite = Section.FindS("Suite"); Dist = Section.FindS("Codename"); -- cgit v1.2.3 From e9737c7f6a3e03b2975927ef9b04c1194026ed9c Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 7 Aug 2013 16:45:49 +0200 Subject: use pkgTagFile to parse "header" of Release files The handwritten parsing here was mostly done as we couldn't trust the Release file we got, but nowadays we are sure that the Release file is valid and contains just a single section we want it to include. Beside reducing code it also fixes a bug: Fieldnames in deb822 formatted files are case-insensitive and pkgTagFile does it correctly, but this selfbuilt stuff here didn't. --- apt-pkg/deb/deblistparser.cc | 104 ++++++++----------------------------------- 1 file changed, 19 insertions(+), 85 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 28857176b..c2707d0a5 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -805,94 +805,28 @@ bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator &FileI, map_ptrloc const storage = WriteUniqString(component); FileI->Component = storage; - // FIXME: should use FileFd and TagSection - FILE* release = fdopen(dup(File.Fd()), "r"); - if (release == NULL) + pkgTagFile TagFile(&File); + pkgTagSection Section; + if (_error->PendingError() == true || TagFile.Step(Section) == false) return false; - char buffer[101]; - while (fgets(buffer, sizeof(buffer), release) != NULL) - { - size_t len = 0; - - // Skip empty lines - for (; buffer[len] == '\r' && buffer[len] == '\n'; ++len) - /* nothing */ - ; - if (buffer[len] == '\0') - continue; - - // seperate the tag from the data - const char* dataStart = strchr(buffer + len, ':'); - if (dataStart == NULL) - continue; - len = dataStart - buffer; - for (++dataStart; *dataStart == ' '; ++dataStart) - /* nothing */ - ; - const char* dataEnd = (const char*)rawmemchr(dataStart, '\0'); - // The last char should be a newline, but we can never be sure: #633350 - const char* lineEnd = dataEnd; - for (--lineEnd; *lineEnd == '\r' || *lineEnd == '\n'; --lineEnd) - /* nothing */ - ; - ++lineEnd; - - // which datastorage need to be updated - enum { Suite, Component, Version, Origin, Codename, Label, None } writeTo = None; - if (buffer[0] == ' ') - ; - #define APT_PARSER_WRITETO(X) else if (strncmp(#X, buffer, len) == 0) writeTo = X; - APT_PARSER_WRITETO(Suite) - APT_PARSER_WRITETO(Component) - APT_PARSER_WRITETO(Version) - APT_PARSER_WRITETO(Origin) - APT_PARSER_WRITETO(Codename) - APT_PARSER_WRITETO(Label) - #undef APT_PARSER_WRITETO - #define APT_PARSER_FLAGIT(X) else if (strncmp(#X, buffer, len) == 0) \ - pkgTagSection::FindFlag(FileI->Flags, pkgCache::Flag:: X, dataStart, lineEnd); - APT_PARSER_FLAGIT(NotAutomatic) - APT_PARSER_FLAGIT(ButAutomaticUpgrades) - #undef APT_PARSER_FLAGIT - - // load all data from the line and save it - string data; - if (writeTo != None) - data.append(dataStart, dataEnd); - if (sizeof(buffer) - 1 == (dataEnd - buffer)) - { - while (fgets(buffer, sizeof(buffer), release) != NULL) - { - if (writeTo != None) - data.append(buffer); - if (strlen(buffer) != sizeof(buffer) - 1) - break; - } - } - if (writeTo != None) - { - // remove spaces and stuff from the end of the data line - for (std::string::reverse_iterator s = data.rbegin(); - s != data.rend(); ++s) - { - if (*s != '\r' && *s != '\n' && *s != ' ') - break; - *s = '\0'; - } - map_ptrloc const storage = WriteUniqString(data); - switch (writeTo) { - case Suite: FileI->Archive = storage; break; - case Component: FileI->Component = storage; break; - case Version: FileI->Version = storage; break; - case Origin: FileI->Origin = storage; break; - case Codename: FileI->Codename = storage; break; - case Label: FileI->Label = storage; break; - case None: break; - } - } + std::string data; + #define APT_INRELEASE(TAG, STORE) \ + data = Section.FindS(TAG); \ + if (data.empty() == false) \ + { \ + map_ptrloc const storage = WriteUniqString(data); \ + STORE = storage; \ } - fclose(release); + APT_INRELEASE("Suite", FileI->Archive) + APT_INRELEASE("Component", FileI->Component) + APT_INRELEASE("Version", FileI->Version) + APT_INRELEASE("Origin", FileI->Origin) + APT_INRELEASE("Codename", FileI->Codename) + APT_INRELEASE("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(); } -- cgit v1.2.3 From f52037d629aea696f938015e7f1ec037eb079af8 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 8 Aug 2013 15:40:15 +0200 Subject: fix -Wall errors --- apt-pkg/deb/dpkgpm.cc | 6 ++++-- apt-pkg/tagfile.h | 2 +- apt-pkg/vendorlist.cc | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index b0bd6b184..34ae4e593 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -134,7 +134,8 @@ static void dpkgChrootDirectory() std::cerr << "Chrooting into " << chrootDir << std::endl; if (chroot(chrootDir.c_str()) != 0) _exit(100); - chdir("/"); + if (chdir("/") != 0) + _exit(100); } /*}}}*/ @@ -755,7 +756,8 @@ bool pkgDPkgPM::OpenLog() pw = getpwnam("root"); gr = getgrnam("adm"); if (pw != NULL && gr != NULL) - chown(logfile_name.c_str(), pw->pw_uid, gr->gr_gid); + if(chown(logfile_name.c_str(), pw->pw_uid, gr->gr_gid) != 0) + _error->Errno("OpenLog", "chown failed"); chmod(logfile_name.c_str(), 0640); fprintf(d->term_out, "\nLog started: %s\n", timestr); } diff --git a/apt-pkg/tagfile.h b/apt-pkg/tagfile.h index 126f4219d..fedd72701 100644 --- a/apt-pkg/tagfile.h +++ b/apt-pkg/tagfile.h @@ -84,7 +84,7 @@ class pkgTagSection Stop = this->Stop; }; - pkgTagSection() : Section(0), TagCount(0), Stop(0), d(NULL) {}; + pkgTagSection() : Section(0), TagCount(0), d(NULL), Stop(0) {}; virtual ~pkgTagSection() {}; }; diff --git a/apt-pkg/vendorlist.cc b/apt-pkg/vendorlist.cc index ecfc7db87..602425624 100644 --- a/apt-pkg/vendorlist.cc +++ b/apt-pkg/vendorlist.cc @@ -66,7 +66,7 @@ bool pkgVendorList::CreateList(Configuration& Cnf) /*{{{*/ Configuration Block(Top); string VendorID = Top->Tag; vector *Fingerprints = new vector; - struct Vendor::Fingerprint *Fingerprint = new struct Vendor::Fingerprint; + struct Vendor::Fingerprint *Fingerprint = new struct Vendor::Fingerprint(); string Origin = Block.Find("Origin"); Fingerprint->Print = Block.Find("Fingerprint"); -- cgit v1.2.3 From 70e0c1683e7021a0682b0808b329a3cced3920ac Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 12 Aug 2013 17:24:15 +0200 Subject: some more coverity fixes --- apt-pkg/acquire-item.cc | 2 ++ apt-pkg/contrib/cmndline.cc | 1 + apt-pkg/contrib/strutl.cc | 2 ++ 3 files changed, 5 insertions(+) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 7bcdf285b..f70cabeff 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -984,6 +984,8 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,string Hash, DestFile += ".decomp"; Desc.URI = decompProg + ":" + FileName; QueueURI(Desc); + + // FIXME: this points to a c++ string that goes out of scope Mode = decompProg.c_str(); } /*}}}*/ diff --git a/apt-pkg/contrib/cmndline.cc b/apt-pkg/contrib/cmndline.cc index 75d02cad4..d77ef4540 100644 --- a/apt-pkg/contrib/cmndline.cc +++ b/apt-pkg/contrib/cmndline.cc @@ -361,6 +361,7 @@ bool CommandLine::DispatchArg(Dispatch *Map,bool NoMatch) void CommandLine::SaveInConfig(unsigned int const &argc, char const * const * const argv) { char cmdline[100 + argc * 50]; + memset(cmdline, 0, sizeof(cmdline)); unsigned int length = 0; bool lastWasOption = false; bool closeQuote = false; diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index df02c3499..b70a62a47 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -943,6 +943,8 @@ bool StrToTime(const string &Val,time_t &Result) Tm.tm_isdst = 0; if (Month[0] != 0) Tm.tm_mon = MonthConv(Month); + else + Tm.tm_mon = 0; // we don't have a month, so pick something Tm.tm_year -= 1900; // Convert to local time and then to GMT -- cgit v1.2.3 From ffcccd62f0d5822a71e24baf84126af5c93a5e69 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 10 Aug 2013 12:40:37 +0200 Subject: fix: --print-uris removes authentication MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The constructors of our (clear)sign-acquire-items move a pre-existent file for error-recovery away, which gets restored or discarded later as the acquire progresses, but --print-uris never really starts the acquire process, so the files aren't restored (as they should). To fix this both get a destructor which checks for signs of acquire doing anything and if it hasn't the file is restored. Note that these virtual destructors theoretically break the API, but only with classes extending the sign-acquire-items and nobody does this, as it would be insane for library users to fiddle with Acquire internals – and these classes are internals. Closes: 719263 --- apt-pkg/acquire-item.cc | 31 +++++++++++++++++++++++++++---- apt-pkg/acquire-item.h | 2 ++ 2 files changed, 29 insertions(+), 4 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 7bcdf285b..95dadcd6d 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -1067,8 +1067,7 @@ pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner, /*{{{*/ string Final = _config->FindDir("Dir::State::lists"); Final += URItoFileName(RealURI); - struct stat Buf; - if (stat(Final.c_str(),&Buf) == 0) + if (RealFileExists(Final) == true) { // File was already in place. It needs to be re-downloaded/verified // because Release might have changed, we do give it a differnt @@ -1080,6 +1079,19 @@ pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner, /*{{{*/ } QueueURI(Desc); +} + /*}}}*/ +pkgAcqMetaSig::~pkgAcqMetaSig() /*{{{*/ +{ + // if the file was never queued undo file-changes done in the constructor + if (QueueCounter == 1 && Status == StatIdle && FileSize == 0 && Complete == false && + LastGoodSig.empty() == false) + { + string const Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI); + if (RealFileExists(Final) == false && RealFileExists(LastGoodSig) == true) + Rename(LastGoodSig, Final); + } + } /*}}}*/ // pkgAcqMetaSig::Custom600Headers - Insert custom request headers /*{{{*/ @@ -1595,14 +1607,25 @@ pkgAcqMetaClearSig::pkgAcqMetaClearSig(pkgAcquire *Owner, /*{{{*/ // keep the old InRelease around in case of transistent network errors string const Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI); - struct stat Buf; - if (stat(Final.c_str(),&Buf) == 0) + if (RealFileExists(Final) == true) { string const LastGoodSig = DestFile + ".reverify"; Rename(Final,LastGoodSig); } } /*}}}*/ +pkgAcqMetaClearSig::~pkgAcqMetaClearSig() /*{{{*/ +{ + // if the file was never queued undo file-changes done in the constructor + if (QueueCounter == 1 && Status == StatIdle && FileSize == 0 && Complete == false) + { + string const Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI); + string const LastGoodSig = DestFile + ".reverify"; + if (RealFileExists(Final) == false && RealFileExists(LastGoodSig) == true) + Rename(LastGoodSig, Final); + } +} + /*}}}*/ // pkgAcqMetaClearSig::Custom600Headers - Insert custom request headers /*{{{*/ // --------------------------------------------------------------------- // FIXME: this can go away once the InRelease file is used widely diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index 51d539450..10c855e63 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -774,6 +774,7 @@ class pkgAcqMetaSig : public pkgAcquire::Item std::string MetaIndexURI, std::string MetaIndexURIDesc, std::string MetaIndexShortDesc, const std::vector* IndexTargets, indexRecords* MetaIndexParser); + virtual ~pkgAcqMetaSig(); }; /*}}}*/ /** \brief An item that is responsible for downloading the meta-index {{{ @@ -904,6 +905,7 @@ public: std::string const &MetaSigURI, std::string const &MetaSigURIDesc, std::string const &MetaSigShortDesc, const std::vector* IndexTargets, indexRecords* MetaIndexParser); + virtual ~pkgAcqMetaClearSig(); }; /*}}}*/ /** \brief An item that is responsible for fetching a package file. {{{ -- cgit v1.2.3 From 11b126f9d229c85bfc7a6092527af46f7314f188 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 13 Jul 2013 23:05:55 +0200 Subject: do not try to chown if not run as root MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If this code is run as non-root we are in a special situation (e.g. in our testcases) where it is obvious that we can't enforce user/group on any file, so skip this code altogether instead of bugging users with an error message – which we also switch to a warning as a failure to open the file is "just" a warning, so the 'wrong' owner shouldn't be that much of an issue. The file is still handled with chmod, so all the security we can enforce is still enforced of course, which also gets a warning if it fails. Git-Dch: Ignore --- apt-pkg/deb/dpkgpm.cc | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 34ae4e593..5b2a8251e 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -751,14 +751,15 @@ bool pkgDPkgPM::OpenLog() return _error->WarningE("OpenLog", _("Could not open file '%s'"), logfile_name.c_str()); setvbuf(d->term_out, NULL, _IONBF, 0); SetCloseExec(fileno(d->term_out), true); - struct passwd *pw; - struct group *gr; - pw = getpwnam("root"); - gr = getgrnam("adm"); - if (pw != NULL && gr != NULL) - if(chown(logfile_name.c_str(), pw->pw_uid, gr->gr_gid) != 0) - _error->Errno("OpenLog", "chown failed"); - chmod(logfile_name.c_str(), 0640); + if (getuid() == 0) // if we aren't root, we can't chown a file, so don't try it + { + struct passwd *pw = getpwnam("root"); + struct group *gr = getgrnam("adm"); + if (pw != NULL && gr != NULL && chown(logfile_name.c_str(), pw->pw_uid, gr->gr_gid) != 0) + _error->WarningE("OpenLog", "chown to root:adm of file %s failed", logfile_name.c_str()); + } + if (chmod(logfile_name.c_str(), 0640) != 0) + _error->WarningE("OpenLog", "chmod 0640 of file %s failed", logfile_name.c_str()); fprintf(d->term_out, "\nLog started: %s\n", timestr); } -- cgit v1.2.3 From 87281603a1342a7dc4d12f979574704a45bf6b7b Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 13 Jul 2013 23:14:41 +0200 Subject: use our _error stack to generate openpty errors While we don't want these error messages on our usual stack, we can use our usual infrastructure to generate an error message with all the usual bells like errno and strerror attached. Git-Dch: Ignore --- apt-pkg/deb/dpkgpm.cc | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 5b2a8251e..959d06455 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1238,16 +1238,13 @@ bool pkgDPkgPM::Go(int OutStatusFd) // if tcgetattr does not return zero there was a error // and we do not do any pty magic - if (tcgetattr(0, &tt) == 0) + _error->PushToStack(); + if (tcgetattr(STDOUT_FILENO, &tt) == 0) { ioctl(0, TIOCGWINSZ, (char *)&win); - if (openpty(&master, &slave, NULL, &tt, &win) < 0) + if (openpty(&master, &slave, NULL, &tt, &win) < 0) { - const char *s = _("Can not write log, openpty() " - "failed (/dev/pts not mounted?)\n"); - fprintf(stderr, "%s",s); - if(d->term_out) - fprintf(d->term_out, "%s",s); + _error->Errno("openpty", _("Can not write log (%s)"), _("Is /dev/pts mounted?")); master = slave = -1; } else { struct termios rtt; @@ -1265,6 +1262,15 @@ bool pkgDPkgPM::Go(int OutStatusFd) sigprocmask(SIG_SETMASK, &original_sigmask, 0); } } + // 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. + else if (isatty(STDOUT_FILENO) == 1 || errno == EBADF) + _error->Errno("tcgetattr", _("Can not write log (%s)"), _("Is stdout a terminal?")); + + if (_error->PendingError() == true) + _error->DumpErrors(std::cerr); + _error->RevertToStack(); + // Fork dpkg pid_t Child; _config->Set("APT::Keep-Fds::",fd[1]); -- cgit v1.2.3 From b917917067e757c4479a344a263ef7cf43c00866 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 12 Aug 2013 23:24:08 +0200 Subject: squash merge of the feature/apt-binary branch without the changes from experimental --- apt-pkg/algorithms.cc | 51 ++++++++++++++++++++++++++++++++---- apt-pkg/algorithms.h | 4 +++ apt-pkg/cachefilter.cc | 11 ++++++++ apt-pkg/cachefilter.h | 35 ++++++++++++++++++++----- apt-pkg/cacheset.cc | 64 +++++++++++++++++++++++++++++++++++++++++++++ apt-pkg/cacheset.h | 13 ++++++++- apt-pkg/contrib/cmndline.cc | 48 ++++++++++++++++++++++++++++++++++ apt-pkg/contrib/cmndline.h | 6 +++++ apt-pkg/contrib/strutl.cc | 12 +++++++++ apt-pkg/contrib/strutl.h | 4 +++ 10 files changed, 236 insertions(+), 12 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 85799a11b..69d4acd83 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -456,6 +456,49 @@ bool pkgAllUpgrade(pkgDepCache &Cache) Cache.MarkInstall(I, false, 0, false); } + return Fix.ResolveByKeep(); +} + /*}}}*/ +// AllUpgradeNoDelete - Upgrade without removing packages /*{{{*/ +// --------------------------------------------------------------------- +/* Right now the system must be consistent before this can be called. + * Upgrade as much as possible without deleting anything (useful for + * stable systems) + */ +bool pkgAllUpgradeNoDelete(pkgDepCache &Cache) +{ + pkgDepCache::ActionGroup group(Cache); + + pkgProblemResolver Fix(&Cache); + + if (Cache.BrokenCount() != 0) + return false; + + // provide the initial set of stuff we want to upgrade by marking + // all upgradable packages for upgrade + for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) + { + if (I->CurrentVer != 0 && Cache[I].InstallVer != 0) + { + if (_config->FindB("APT::Ignore-Hold",false) == false) + if (I->SelectedState == pkgCache::State::Hold) + continue; + + Cache.MarkInstall(I, false, 0, false); + } + } + + // then let auto-install loose + for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) + if (Cache[I].Install()) + Cache.MarkInstall(I, true, 0, false); + + // ... but it may remove stuff, we we need to clean up afterwards again + for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) + if (Cache[I].Delete() == true) + Cache.MarkKeep(I, false, false); + + // resolve remaining issues via keep return Fix.ResolveByKeep(); } /*}}}*/ @@ -550,14 +593,12 @@ void pkgProblemResolver::MakeScores() unsigned long Size = Cache.Head().PackageCount; memset(Scores,0,sizeof(*Scores)*Size); - // Maps to pkgCache::State::VerPriority - // which is "Important Required Standard Optional Extra" - // (yes, that is confusing, the order of pkgCache::State::VerPriority - // needs to be adjusted but that requires a ABI break) + // maps to pkgCache::State::VerPriority: + // Required Important Standard Optional Extra int PrioMap[] = { 0, - _config->FindI("pkgProblemResolver::Scores::Important",2), _config->FindI("pkgProblemResolver::Scores::Required",3), + _config->FindI("pkgProblemResolver::Scores::Important",2), _config->FindI("pkgProblemResolver::Scores::Standard",1), _config->FindI("pkgProblemResolver::Scores::Optional",-1), _config->FindI("pkgProblemResolver::Scores::Extra",-2) diff --git a/apt-pkg/algorithms.h b/apt-pkg/algorithms.h index 7f58c8eed..a499db8ba 100644 --- a/apt-pkg/algorithms.h +++ b/apt-pkg/algorithms.h @@ -143,7 +143,11 @@ class pkgProblemResolver /*{{{*/ bool pkgDistUpgrade(pkgDepCache &Cache); bool pkgApplyStatus(pkgDepCache &Cache); bool pkgFixBroken(pkgDepCache &Cache); + bool pkgAllUpgrade(pkgDepCache &Cache); + +bool pkgAllUpgradeNoDelete(pkgDepCache &Cache); + bool pkgMinimizeUpgrade(pkgDepCache &Cache); void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List); diff --git a/apt-pkg/cachefilter.cc b/apt-pkg/cachefilter.cc index 64cde41d1..57b9af159 100644 --- a/apt-pkg/cachefilter.cc +++ b/apt-pkg/cachefilter.cc @@ -55,6 +55,17 @@ PackageNameMatchesRegEx::~PackageNameMatchesRegEx() { /*{{{*/ } /*}}}*/ +// Fnmatch support /*{{{*/ +//---------------------------------------------------------------------- +bool PackageNameMatchesFnmatch::operator() (pkgCache::PkgIterator const &Pkg) {/*{{{*/ + return fnmatch(Pattern.c_str(), Pkg.Name(), FNM_CASEFOLD) == 0; +} + /*}}}*/ +bool PackageNameMatchesFnmatch::operator() (pkgCache::GrpIterator const &Grp) {/*{{{*/ + return fnmatch(Pattern.c_str(), Grp.Name(), FNM_CASEFOLD) == 0; +} + /*}}}*/ + // CompleteArch to - tuple /*{{{*/ //---------------------------------------------------------------------- /* The complete architecture, consisting of -. */ diff --git a/apt-pkg/cachefilter.h b/apt-pkg/cachefilter.h index 25cd43f47..f55d5c7f7 100644 --- a/apt-pkg/cachefilter.h +++ b/apt-pkg/cachefilter.h @@ -14,18 +14,41 @@ /*}}}*/ namespace APT { namespace CacheFilter { + +class PackageMatcher { + public: + virtual bool operator() (pkgCache::PkgIterator const &Pkg) { return false; }; + virtual bool operator() (pkgCache::GrpIterator const &Grp) { return false; }; + virtual bool operator() (pkgCache::VerIterator const &Ver) { return false; }; + + virtual ~PackageMatcher() {}; +}; + // PackageNameMatchesRegEx /*{{{*/ -class PackageNameMatchesRegEx { +class PackageNameMatchesRegEx : public PackageMatcher { /** \brief dpointer placeholder (for later in case we need it) */ void *d; regex_t* pattern; public: PackageNameMatchesRegEx(std::string const &Pattern); - bool operator() (pkgCache::PkgIterator const &Pkg); - bool operator() (pkgCache::GrpIterator const &Grp); + virtual bool operator() (pkgCache::PkgIterator const &Pkg); + virtual bool operator() (pkgCache::GrpIterator const &Grp); ~PackageNameMatchesRegEx(); }; /*}}}*/ +// PackageNameMatchesFnmatch /*{{{*/ + class PackageNameMatchesFnmatch : public PackageMatcher{ + /** \brief dpointer placeholder (for later in case we need it) */ + void *d; + const std::string Pattern; +public: + PackageNameMatchesFnmatch(std::string const &Pattern) + : Pattern(Pattern) {}; + virtual bool operator() (pkgCache::PkgIterator const &Pkg); + virtual bool operator() (pkgCache::GrpIterator const &Grp); + ~PackageNameMatchesFnmatch() {}; +}; + /*}}}*/ // PackageArchitectureMatchesSpecification /*{{{*/ /** \class PackageArchitectureMatchesSpecification \brief matching against architecture specification strings @@ -35,7 +58,7 @@ public: debian-policy §11.1 "Architecture specification strings". Examples: i386, mipsel, linux-any, any-amd64, any */ -class PackageArchitectureMatchesSpecification { +class PackageArchitectureMatchesSpecification : public PackageMatcher { std::string literal; std::string complete; bool isPattern; @@ -51,8 +74,8 @@ public: */ PackageArchitectureMatchesSpecification(std::string const &pattern, bool const isPattern = true); bool operator() (char const * const &arch); - bool operator() (pkgCache::PkgIterator const &Pkg); - bool operator() (pkgCache::VerIterator const &Ver); + virtual bool operator() (pkgCache::PkgIterator const &Pkg); + virtual bool operator() (pkgCache::VerIterator const &Ver); ~PackageArchitectureMatchesSpecification(); }; /*}}}*/ diff --git a/apt-pkg/cacheset.cc b/apt-pkg/cacheset.cc index 1fea4f94a..0147f7e86 100644 --- a/apt-pkg/cacheset.cc +++ b/apt-pkg/cacheset.cc @@ -149,6 +149,69 @@ bool PackageContainerInterface::FromRegEx(PackageContainerInterface * const pci, return false; } + if (wasEmpty == false && pci->getConstructor() != UNKNOWN) + pci->setConstructor(UNKNOWN); + + return true; +} + /*}}}*/ +// FromFnmatch - Returns the package defined by this fnmatch /*{{{*/ +bool +PackageContainerInterface::FromFnmatch(PackageContainerInterface * const pci, + pkgCacheFile &Cache, + std::string pattern, + CacheSetHelper &helper) +{ + static const char * const isfnmatch = ".?*[]!"; + if (pattern.find_first_of(isfnmatch) == std::string::npos) + return false; + + bool const wasEmpty = pci->empty(); + if (wasEmpty == true) + pci->setConstructor(FNMATCH); + + size_t archfound = pattern.find_last_of(':'); + std::string arch = "native"; + if (archfound != std::string::npos) { + arch = pattern.substr(archfound+1); + if (arch.find_first_of(isfnmatch) == std::string::npos) + pattern.erase(archfound); + else + arch = "native"; + } + + if (unlikely(Cache.GetPkgCache() == 0)) + return false; + + APT::CacheFilter::PackageNameMatchesFnmatch filter(pattern); + + bool found = false; + for (pkgCache::GrpIterator Grp = Cache.GetPkgCache()->GrpBegin(); Grp.end() == false; ++Grp) { + if (filter(Grp) == false) + continue; + pkgCache::PkgIterator Pkg = Grp.FindPkg(arch); + if (Pkg.end() == true) { + if (archfound == std::string::npos) { + std::vector archs = APT::Configuration::getArchitectures(); + for (std::vector::const_iterator a = archs.begin(); + a != archs.end() && Pkg.end() != true; ++a) + Pkg = Grp.FindPkg(*a); + } + if (Pkg.end() == true) + continue; + } + + pci->insert(Pkg); + helper.showRegExSelection(Pkg, pattern); + found = true; + } + + if (found == false) { + helper.canNotFindRegEx(pci, Cache, pattern); + pci->setConstructor(UNKNOWN); + return false; + } + if (wasEmpty == false && pci->getConstructor() != UNKNOWN) pci->setConstructor(UNKNOWN); @@ -239,6 +302,7 @@ bool PackageContainerInterface::FromString(PackageContainerInterface * const pci if (FromGroup(pci, Cache, str, helper) == false && FromTask(pci, Cache, str, helper) == false && + FromFnmatch(pci, Cache, str, helper) == false && FromRegEx(pci, Cache, str, helper) == false) { helper.canNotFindPackage(pci, Cache, str); diff --git a/apt-pkg/cacheset.h b/apt-pkg/cacheset.h index d7328d705..29103aad9 100644 --- a/apt-pkg/cacheset.h +++ b/apt-pkg/cacheset.h @@ -131,13 +131,14 @@ public: virtual bool empty() const = 0; virtual void clear() = 0; - enum Constructor { UNKNOWN, REGEX, TASK }; + enum Constructor { UNKNOWN, REGEX, TASK, FNMATCH }; virtual void setConstructor(Constructor const &con) = 0; virtual Constructor getConstructor() const = 0; static bool FromTask(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper); static bool FromRegEx(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper); static pkgCache::PkgIterator FromName(pkgCacheFile &Cache, std::string const &pattern, CacheSetHelper &helper); + static bool FromFnmatch(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper); static bool FromGroup(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper); static bool FromString(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string const &pattern, CacheSetHelper &helper); static bool FromCommandLine(PackageContainerInterface * const pci, pkgCacheFile &Cache, const char **cmdline, CacheSetHelper &helper); @@ -259,6 +260,16 @@ public: /*{{{*/ return FromRegEx(Cache, pattern, helper); } + static PackageContainer FromFnmatch(pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper) { + PackageContainer cont(FNMATCH); + PackageContainerInterface::FromFnmatch(&cont, Cache, pattern, helper); + return cont; + } + static PackageContainer FromFnMatch(pkgCacheFile &Cache, std::string const &pattern) { + CacheSetHelper helper; + return FromFnmatch(Cache, pattern, helper); + } + /** \brief returns a package specified by a string \param Cache the package is in diff --git a/apt-pkg/contrib/cmndline.cc b/apt-pkg/contrib/cmndline.cc index 75d02cad4..8cef80368 100644 --- a/apt-pkg/contrib/cmndline.cc +++ b/apt-pkg/contrib/cmndline.cc @@ -38,6 +38,42 @@ CommandLine::~CommandLine() delete [] FileList; } /*}}}*/ +// CommandLine::GetCommand - return the first non-option word /*{{{*/ +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 + for (size_t i = 1; i < argc; ++i) + { + if (strcmp(argv[i], "--") != 0) + continue; + ++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; + i -= 2; + if (i != 0) + for (size_t j = 0; Map[j].Match != NULL; ++j) + if (strcmp(argv[i], Map[j].Match) == 0) + return Map[j].Match; + return NULL; + } + // no --, so search for the first word matching a command + // FIXME: How like is it that an option parameter will be also a valid Match ? + for (size_t i = 1; i < argc; ++i) + { + if (*(argv[i]) == '-') + continue; + for (size_t j = 0; Map[j].Match != NULL; ++j) + if (strcmp(argv[i], Map[j].Match) == 0) + return Map[j].Match; + } + return NULL; +} + /*}}}*/ // CommandLine::Parse - Main action member /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -390,3 +426,15 @@ void CommandLine::SaveInConfig(unsigned int const &argc, char const * const * co _config->Set("CommandLine::AsString", cmdline); } /*}}}*/ +CommandLine::Args CommandLine::MakeArgs(char ShortOpt, char const *LongOpt, char const *ConfName, unsigned long Flags)/*{{{*/ +{ + /* In theory, this should be a constructor for CommandLine::Args instead, + but this breaks compatibility as gcc thinks this is a c++11 initializer_list */ + CommandLine::Args arg; + arg.ShortOpt = ShortOpt; + arg.LongOpt = LongOpt; + arg.ConfName = ConfName; + arg.Flags = Flags; + return arg; +} + /*}}}*/ diff --git a/apt-pkg/contrib/cmndline.h b/apt-pkg/contrib/cmndline.h index 9f505fd41..180276633 100644 --- a/apt-pkg/contrib/cmndline.h +++ b/apt-pkg/contrib/cmndline.h @@ -83,6 +83,12 @@ class CommandLine unsigned int FileSize() const; bool DispatchArg(Dispatch *List,bool NoMatch = true); + static char const * GetCommand(Dispatch const * const Map, + unsigned int const argc, char const * const * const argv); + + static CommandLine::Args MakeArgs(char ShortOpt, char const *LongOpt, + char const *ConfName, unsigned long Flags); + CommandLine(Args *AList,Configuration *Conf); ~CommandLine(); }; diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index df02c3499..d06637155 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -1291,6 +1291,18 @@ bool CheckDomainList(const string &Host,const string &List) return false; } /*}}}*/ +// strv_length - Return the length of a NULL-terminated string array /*{{{*/ +// --------------------------------------------------------------------- +/* */ +size_t strv_length(const char **str_array) +{ + size_t i; + for (i=0; str_array[i] != NULL; i++) + /* nothing */ + ; + return i; +} + // DeEscapeString - unescape (\0XX and \xXX) from a string /*{{{*/ // --------------------------------------------------------------------- /* */ diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h index e92f91dc0..530896141 100644 --- a/apt-pkg/contrib/strutl.h +++ b/apt-pkg/contrib/strutl.h @@ -108,6 +108,10 @@ inline int stringcasecmp(std::string::const_iterator A,std::string::const_iterat APT_MKSTRCMP2(stringcmp,stringcmp); APT_MKSTRCMP2(stringcasecmp,stringcasecmp); +// Return the length of a NULL-terminated string array +size_t strv_length(const char **str_array); + + inline const char *DeNull(const char *s) {return (s == 0?"(null)":s);}; class URI -- cgit v1.2.3 From 314a3f88fb099edd74e5899d8d95ef35984e7a24 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 15 Aug 2013 09:04:25 +0200 Subject: make destructors virtual --- apt-pkg/cachefilter.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/cachefilter.h b/apt-pkg/cachefilter.h index f55d5c7f7..ddd8df16e 100644 --- a/apt-pkg/cachefilter.h +++ b/apt-pkg/cachefilter.h @@ -33,7 +33,7 @@ public: PackageNameMatchesRegEx(std::string const &Pattern); virtual bool operator() (pkgCache::PkgIterator const &Pkg); virtual bool operator() (pkgCache::GrpIterator const &Grp); - ~PackageNameMatchesRegEx(); + virtual ~PackageNameMatchesRegEx(); }; /*}}}*/ // PackageNameMatchesFnmatch /*{{{*/ @@ -46,7 +46,7 @@ public: : Pattern(Pattern) {}; virtual bool operator() (pkgCache::PkgIterator const &Pkg); virtual bool operator() (pkgCache::GrpIterator const &Grp); - ~PackageNameMatchesFnmatch() {}; + virtual ~PackageNameMatchesFnmatch() {}; }; /*}}}*/ // PackageArchitectureMatchesSpecification /*{{{*/ @@ -76,7 +76,7 @@ public: bool operator() (char const * const &arch); virtual bool operator() (pkgCache::PkgIterator const &Pkg); virtual bool operator() (pkgCache::VerIterator const &Ver); - ~PackageArchitectureMatchesSpecification(); + virtual ~PackageArchitectureMatchesSpecification(); }; /*}}}*/ } -- cgit v1.2.3 From d8a06f6e478323b2fa8573f6f885c0b16d403642 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Wed, 17 Oct 2012 10:29:52 +0200 Subject: * lp:~mvo/apt/config-clear: - support Configuration.Clear() for a clear of the entire configuration Conflicts: debian/changelog --- apt-pkg/contrib/configuration.cc | 12 ++++++++++++ apt-pkg/contrib/configuration.h | 1 + 2 files changed, 13 insertions(+) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/configuration.cc b/apt-pkg/contrib/configuration.cc index 376617401..4ef4663c0 100644 --- a/apt-pkg/contrib/configuration.cc +++ b/apt-pkg/contrib/configuration.cc @@ -420,6 +420,18 @@ void Configuration::Clear(string const &Name, string const &Value) } } +} + /*}}}*/ +// Configuration::Clear - Clear everything /*{{{*/ +// --------------------------------------------------------------------- +void Configuration::Clear() +{ + const Configuration::Item *Top = Tree(0); + while( Top != 0 ) + { + Clear(Top->FullTag()); + Top = Top->Next; + } } /*}}}*/ // Configuration::Clear - Clear an entire tree /*{{{*/ diff --git a/apt-pkg/contrib/configuration.h b/apt-pkg/contrib/configuration.h index ea94c2fe6..8e09ea0a6 100644 --- a/apt-pkg/contrib/configuration.h +++ b/apt-pkg/contrib/configuration.h @@ -94,6 +94,7 @@ class Configuration // clear a whole tree void Clear(const std::string &Name); + void Clear(); // remove a certain value from a list (e.g. the list of "APT::Keep-Fds") void Clear(std::string const &List, std::string const &Value); -- cgit v1.2.3 From 488011fa99aee25bedb39ae2cc3115ad1ab000c0 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Wed, 17 Oct 2012 10:27:50 +0200 Subject: * lp:~mvo/apt/add-glob-function: - add Glob() to fileutl.{cc,h} Conflicts: apt-pkg/contrib/fileutl.h debian/changelog --- apt-pkg/contrib/fileutl.cc | 31 +++++++++++++++++++++++++++++++ apt-pkg/contrib/fileutl.h | 3 +++ 2 files changed, 34 insertions(+) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index f24df65fc..dca468c63 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -41,6 +41,8 @@ #include #include #include +#include + #include #include @@ -1766,3 +1768,32 @@ bool FileFd::FileFdError(const char *Description,...) { /*}}}*/ gzFile FileFd::gzFd() { return (gzFile) d->gz; } + + +// Glob - wrapper around "glob()" /*{{{*/ +// --------------------------------------------------------------------- +/* */ +std::vector Glob(std::string const &pattern, int flags) +{ + std::vector result; + glob_t globbuf; + int glob_res, i; + + glob_res = glob(pattern.c_str(), flags, NULL, &globbuf); + + if (glob_res != 0) + { + if(glob_res != GLOB_NOMATCH) { + _error->Errno("glob", "Problem with glob"); + return result; + } + } + + // append results + for(i=0;i Glob(std::string const &pattern, int flags=0); + #endif -- cgit v1.2.3 From dd4d9729975fc2de37cd69220bc05efb16badc77 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 15 Aug 2013 13:39:32 +0200 Subject: add PACKAGE_MATCHER_ABI_COMPAT mode for now so that this branch can be merged without breaking ABI --- apt-pkg/cachefilter.h | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/cachefilter.h b/apt-pkg/cachefilter.h index ddd8df16e..34b7d0b46 100644 --- a/apt-pkg/cachefilter.h +++ b/apt-pkg/cachefilter.h @@ -15,6 +15,66 @@ namespace APT { namespace CacheFilter { +#define PACKAGE_MATCHER_ABI_COMPAT 1 +#ifdef PACKAGE_MATCHER_ABI_COMPAT + +// PackageNameMatchesRegEx /*{{{*/ +class PackageNameMatchesRegEx { + /** \brief dpointer placeholder (for later in case we need it) */ + void *d; + regex_t* pattern; +public: + PackageNameMatchesRegEx(std::string const &Pattern); + bool operator() (pkgCache::PkgIterator const &Pkg); + bool operator() (pkgCache::GrpIterator const &Grp); + ~PackageNameMatchesRegEx(); +}; + /*}}}*/ +// PackageNameMatchesFnmatch /*{{{*/ + class PackageNameMatchesFnmatch { + /** \brief dpointer placeholder (for later in case we need it) */ + void *d; + const std::string Pattern; +public: + PackageNameMatchesFnmatch(std::string const &Pattern) + : Pattern(Pattern) {}; + bool operator() (pkgCache::PkgIterator const &Pkg); + bool operator() (pkgCache::GrpIterator const &Grp); + ~PackageNameMatchesFnmatch() {}; +}; + /*}}}*/ +// PackageArchitectureMatchesSpecification /*{{{*/ +/** \class PackageArchitectureMatchesSpecification + \brief matching against architecture specification strings + + The strings are of the format - where either component, + or the whole string, can be the wildcard "any" as defined in + debian-policy §11.1 "Architecture specification strings". + + Examples: i386, mipsel, linux-any, any-amd64, any */ +class PackageArchitectureMatchesSpecification { + std::string literal; + std::string complete; + bool isPattern; + /** \brief dpointer placeholder (for later in case we need it) */ + void *d; +public: + /** \brief matching against architecture specification strings + * + * @param pattern is the architecture specification string + * @param isPattern defines if the given \b pattern is a + * architecture specification pattern to match others against + * or if it is the fixed string and matched against patterns + */ + PackageArchitectureMatchesSpecification(std::string const &pattern, bool const isPattern = true); + bool operator() (char const * const &arch); + bool operator() (pkgCache::PkgIterator const &Pkg); + bool operator() (pkgCache::VerIterator const &Ver); + ~PackageArchitectureMatchesSpecification(); +}; + +#else + class PackageMatcher { public: virtual bool operator() (pkgCache::PkgIterator const &Pkg) { return false; }; @@ -37,7 +97,7 @@ public: }; /*}}}*/ // PackageNameMatchesFnmatch /*{{{*/ - class PackageNameMatchesFnmatch : public PackageMatcher{ + class PackageNameMatchesFnmatch : public PackageMatcher{ /** \brief dpointer placeholder (for later in case we need it) */ void *d; const std::string Pattern; @@ -78,6 +138,7 @@ public: virtual bool operator() (pkgCache::VerIterator const &Ver); virtual ~PackageArchitectureMatchesSpecification(); }; +#endif /*}}}*/ } } -- cgit v1.2.3 From 233d79a51cc6b922b3f0be0f5c3b460f8ea50d36 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 13 Aug 2013 21:46:32 +0200 Subject: init the pkgTagFile with the size of the Release file Release files are basically one big Section, so we might safe some Resize circles by starting with the filesize. Git-Dch: Ignore --- apt-pkg/deb/deblistparser.cc | 2 +- apt-pkg/indexrecords.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index c2707d0a5..87aab6ee2 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -805,7 +805,7 @@ bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator &FileI, map_ptrloc const storage = WriteUniqString(component); FileI->Component = storage; - pkgTagFile TagFile(&File); + pkgTagFile TagFile(&File, File.Size()); pkgTagSection Section; if (_error->PendingError() == true || TagFile.Step(Section) == false) return false; diff --git a/apt-pkg/indexrecords.cc b/apt-pkg/indexrecords.cc index 6d89949a0..8a72ca151 100644 --- a/apt-pkg/indexrecords.cc +++ b/apt-pkg/indexrecords.cc @@ -62,7 +62,7 @@ bool indexRecords::Load(const string Filename) /*{{{*/ if (OpenMaybeClearSignedFile(Filename, Fd) == false) return false; - pkgTagFile TagFile(&Fd); + pkgTagFile TagFile(&Fd, Fd.Size()); if (_error->PendingError() == true) { strprintf(ErrorText, _("Unable to parse Release file %s"),Filename.c_str()); -- cgit v1.2.3 From 0aae6d14390193e25ab6d0fd49295bd7b131954f Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 15 Aug 2013 16:49:51 +0200 Subject: ensure that pkgTagFile isn't writing past Buffer length In 91c4cc14d3654636edf997d23852f05ad3de4853 I removed the +256 from the pkgTagFile call parsing Release files as I couldn't find a mentioning of a reason for why and it was marked as XXX which suggested that at least someone else was suspicious. It turns out that it is indeed "documented", it just didn't found it at first but the changelog of apt 0.6.6 (29. Dec 2003) mentions: * Restore the ugly hack I removed from indexRecords::Load which set the pkgTagFile buffer size to (file size)+256. This is concealing a bug, but I can't fix it right now. This should fix the segfaults that folks are seeing with 0.6.[45]. The bug it is "hiding" is that if pkgTagFile works with a file which doesn't end in a double newline it will be adding it without checking if the Buffer is big enough to store them. Its also not a good idea to let the End pointer be past the end of our space, even if we don't access the data. Closes: 719629 --- apt-pkg/tagfile.cc | 33 ++++++++++++++++++++++++--------- apt-pkg/tagfile.h | 1 + 2 files changed, 25 insertions(+), 9 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc index 1c79ee74f..aa0f1eee8 100644 --- a/apt-pkg/tagfile.cc +++ b/apt-pkg/tagfile.cc @@ -50,6 +50,11 @@ public: /* */ pkgTagFile::pkgTagFile(FileFd *pFd,unsigned long long Size) { + /* The size is increased by 4 because if we start with the Size of the + filename we need to try to read 1 char more to see an EOF faster, 1 + char the end-pointer can be on and maybe 2 newlines need to be added + to the end of the file -> 4 extra chars */ + Size += 4; d = new pkgTagFilePrivate(pFd, Size); if (d->Fd.IsOpen() == false) @@ -89,17 +94,21 @@ unsigned long pkgTagFile::Offset() */ bool pkgTagFile::Resize() { - char *tmp; - unsigned long long EndSize = d->End - d->Start; - // fail is the buffer grows too big if(d->Size > 1024*1024+1) return false; + return Resize(d->Size * 2); +} +bool pkgTagFile::Resize(unsigned long long const newSize) +{ + unsigned long long const EndSize = d->End - d->Start; + char *tmp; + // get new buffer and use it - tmp = new char[2*d->Size]; + tmp = new char[newSize]; memcpy(tmp, d->Buffer, d->Size); - d->Size = d->Size*2; + d->Size = newSize; delete [] d->Buffer; d->Buffer = tmp; @@ -152,9 +161,10 @@ bool pkgTagFile::Fill() if (d->Done == false) { // See if only a bit of the file is left - if (d->Fd.Read(d->End, d->Size - (d->End - d->Buffer),&Actual) == false) + unsigned long long const dataSize = d->Size - ((d->End - d->Buffer) + 1); + if (d->Fd.Read(d->End, dataSize, &Actual) == false) return false; - if (Actual != d->Size - (d->End - d->Buffer)) + if (Actual != dataSize || d->Fd.Eof() == true) d->Done = true; d->End += Actual; } @@ -171,8 +181,13 @@ bool pkgTagFile::Fill() for (const char *E = d->End - 1; E - d->End < 6 && (*E == '\n' || *E == '\r'); E--) if (*E == '\n') LineCount++; - for (; LineCount < 2; LineCount++) - *d->End++ = '\n'; + if (LineCount < 2) + { + if ((unsigned)(d->End - d->Buffer) >= d->Size) + Resize(d->Size + 3); + for (; LineCount < 2; LineCount++) + *d->End++ = '\n'; + } return true; } diff --git a/apt-pkg/tagfile.h b/apt-pkg/tagfile.h index fedd72701..66c56799d 100644 --- a/apt-pkg/tagfile.h +++ b/apt-pkg/tagfile.h @@ -95,6 +95,7 @@ class pkgTagFile bool Fill(); bool Resize(); + bool Resize(unsigned long long const newSize); public: -- cgit v1.2.3 From 4b2803b8ff72b0c865c6539b2f99abea5ceee4c6 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 15 Aug 2013 17:26:30 +0200 Subject: use malloc instead of new[] in pkgTagFile We don't need initialized memory for pkgTagFile, but more to the point we can use realloc this way which hides the bloody details of increasing the size of the buffer used. Git-Dch: Ignore --- apt-pkg/tagfile.cc | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc index aa0f1eee8..10bc08d95 100644 --- a/apt-pkg/tagfile.cc +++ b/apt-pkg/tagfile.cc @@ -58,18 +58,19 @@ pkgTagFile::pkgTagFile(FileFd *pFd,unsigned long long Size) d = new pkgTagFilePrivate(pFd, Size); if (d->Fd.IsOpen() == false) - { d->Start = d->End = d->Buffer = 0; + else + d->Buffer = (char*)malloc(sizeof(char) * Size); + + if (d->Buffer == NULL) d->Done = true; - d->iOffset = 0; - return; - } - - d->Buffer = new char[Size]; + else + d->Done = false; + d->Start = d->End = d->Buffer; - d->Done = false; d->iOffset = 0; - Fill(); + if (d->Done == false) + Fill(); } /*}}}*/ // TagFile::~pkgTagFile - Destructor /*{{{*/ @@ -77,11 +78,11 @@ pkgTagFile::pkgTagFile(FileFd *pFd,unsigned long long Size) /* */ pkgTagFile::~pkgTagFile() { - delete [] d->Buffer; + free(d->Buffer); delete d; } /*}}}*/ -// TagFile::Offset - Return the current offset in the buffer /*{{{*/ +// TagFile::Offset - Return the current offset in the buffer /*{{{*/ unsigned long pkgTagFile::Offset() { return d->iOffset; @@ -103,14 +104,13 @@ bool pkgTagFile::Resize() bool pkgTagFile::Resize(unsigned long long const newSize) { unsigned long long const EndSize = d->End - d->Start; - char *tmp; // get new buffer and use it - tmp = new char[newSize]; - memcpy(tmp, d->Buffer, d->Size); + char* newBuffer = (char*)realloc(d->Buffer, sizeof(char) * newSize); + if (newBuffer == NULL) + return false; + d->Buffer = newBuffer; d->Size = newSize; - delete [] d->Buffer; - d->Buffer = tmp; // update the start/end pointers to the new buffer d->Start = d->Buffer; -- cgit v1.2.3 From 48498443e74b2a7e089709b954c50b7df374684b Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 13 Aug 2013 18:18:15 +0200 Subject: allow Pre-Install-Pkgs hooks to get info over an FD != stdin This adds ::InfoFD option alongside the ::Version one to request sending the information to the specified FD, by default it is STDIN as it was the case before. The environment variable APT_HOOK_INFO_FD contains the FD the data is on as a confirmation that the APT version used understood the request. Allowing the hook to choose the FD is needed/helpful e.g. for shellscripts which have a hard time accessing FDs above 9 (as >= 10 are usually used internally by them) Closes: #671728 --- apt-pkg/deb/dpkgpm.cc | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 959d06455..4b5467eff 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -382,24 +382,32 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf) OptSec = "DPkg::Tools::Options::" + string(Opts->Value.c_str(),Pos); unsigned int Version = _config->FindI(OptSec+"::Version",1); + unsigned int InfoFD = _config->FindI(OptSec + "::InfoFD", STDIN_FILENO); // Create the pipes int Pipes[2]; if (pipe(Pipes) != 0) return _error->Errno("pipe","Failed to create IPC pipe to subprocess"); - SetCloseExec(Pipes[0],true); + if (InfoFD != (unsigned)Pipes[0]) + SetCloseExec(Pipes[0],true); + else + _config->Set("APT::Keep-Fds::", Pipes[0]); SetCloseExec(Pipes[1],true); - + // Purified Fork for running the script - pid_t Process = ExecFork(); + pid_t Process = ExecFork(); if (Process == 0) { // Setup the FDs - dup2(Pipes[0],STDIN_FILENO); + dup2(Pipes[0], InfoFD); SetCloseExec(STDOUT_FILENO,false); - SetCloseExec(STDIN_FILENO,false); + SetCloseExec(STDIN_FILENO,false); SetCloseExec(STDERR_FILENO,false); + string hookfd; + strprintf(hookfd, "%d", InfoFD); + setenv("APT_HOOK_INFO_FD", hookfd.c_str(), 1); + dpkgChrootDirectory(); const char *Args[4]; Args[0] = "/bin/sh"; @@ -409,6 +417,8 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf) execv(Args[0],(char **)Args); _exit(100); } + if (InfoFD == (unsigned)Pipes[0]) + _config->Clear("APT::Keep-Fds", Pipes[0]); close(Pipes[0]); FILE *F = fdopen(Pipes[1],"w"); if (F == 0) -- cgit v1.2.3 From ec4835a14aae3d4995894c44ec4c4801bac0235d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81ngel=20Guzm=C3=A1n=20Maeso?= Date: Wed, 21 Aug 2013 19:38:35 +0200 Subject: apt-pkg:contrib Avoid compiler warning about sign-compare MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The fix avoid the warning "comparison between signed and unsigned integer expressions [-Wsign-compare]"· The index for the loop needs to be unsigned for compare with globbuf.gl_pathc structure member --- 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 dca468c63..47a91c294 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -1777,7 +1777,8 @@ std::vector Glob(std::string const &pattern, int flags) { std::vector result; glob_t globbuf; - int glob_res, i; + int glob_res; + unsigned int i; glob_res = glob(pattern.c_str(), flags, NULL, &globbuf); -- cgit v1.2.3 From 2510eea4a0922b7b6da8099deb70ca87851633ce Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 22 Aug 2013 22:30:20 +0200 Subject: do chdir("/") after chroot() --- apt-pkg/aptconfiguration.cc | 2 +- apt-pkg/tagfile.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/aptconfiguration.cc b/apt-pkg/aptconfiguration.cc index e32e553a4..4f9b84e00 100644 --- a/apt-pkg/aptconfiguration.cc +++ b/apt-pkg/aptconfiguration.cc @@ -392,7 +392,7 @@ std::vector const Configuration::getArchitectures(bool const &Cache dup2(nullfd, STDIN_FILENO); dup2(external[1], STDOUT_FILENO); dup2(nullfd, STDERR_FILENO); - if (chrootDir != "/" && chroot(chrootDir.c_str()) != 0) + if (chrootDir != "/" && chroot(chrootDir.c_str()) != 0 && chdir("/") != 0) _error->WarningE("getArchitecture", "Couldn't chroot into %s for dpkg --print-foreign-architectures", chrootDir.c_str()); execvp(Args[0], (char**) &Args[0]); _error->WarningE("getArchitecture", "Can't detect foreign architectures supported by dpkg!"); diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc index 868adf3d2..b91e868e2 100644 --- a/apt-pkg/tagfile.cc +++ b/apt-pkg/tagfile.cc @@ -237,7 +237,7 @@ bool pkgTagFile::Jump(pkgTagSection &Tag,unsigned long long Offset) // --------------------------------------------------------------------- /* */ pkgTagSection::pkgTagSection() - : Section(0), TagCount(0), Stop(0), d(NULL) + : Section(0), TagCount(0), d(NULL), Stop(0) { memset(&Indexes, 0, sizeof(Indexes)); memset(&AlphaIndexes, 0, sizeof(AlphaIndexes)); -- cgit v1.2.3 From 51fc6def77edfb1f429a48e5169519e9e05a759b Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 26 Aug 2013 21:09:33 +0200 Subject: set Acquire::PDiffs::FileLimit to 20 to avoid needless huge fetches --- 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 97b2d1e29..da00c9dd5 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -434,7 +434,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile) /*{{{*/ if (available_patches.empty() == false) { // patching with too many files is rather slow compared to a fast download - unsigned long const fileLimit = _config->FindI("Acquire::PDiffs::FileLimit", 0); + unsigned long const fileLimit = _config->FindI("Acquire::PDiffs::FileLimit", 20); if (fileLimit != 0 && fileLimit < available_patches.size()) { if (Debug) -- cgit v1.2.3 From 7335eebea6dd43581d4650a8818b06383ab89901 Mon Sep 17 00:00:00 2001 From: Angel Guzman Maeso Date: Tue, 27 Aug 2013 21:29:01 +0200 Subject: replace usage of potential dangerous mktemp with mkstemp Avoid the warning "the use of `mktemp' is dangerous, better use `mkstemp' or `mkdtemp'". It is not strictly necessary to change the usage from a security point of view here, but mktemp is also removed from the standard since POSIX.1-2008. The mkostemp call returns a file descriptor the logic for TemporaryFileName has been changed accordingly to get the same results. The file permissions are corrected by using fchmod() as the default for FileFd is 666 while mkstemp creates files with 600 by default. --- apt-pkg/contrib/fileutl.cc | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 47a91c294..3eeef58cf 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -946,9 +946,6 @@ bool FileFd::Open(string FileName,unsigned int const Mode,APT::Configuration::Co if ((Mode & Atomic) == Atomic) { Flags |= Replace; - char *name = strdup((FileName + ".XXXXXX").c_str()); - TemporaryFileName = string(mktemp(name)); - free(name); } else if ((Mode & (Exclusive | Create)) == (Exclusive | Create)) { @@ -974,8 +971,25 @@ bool FileFd::Open(string FileName,unsigned int const Mode,APT::Configuration::Co else if_FLAGGED_SET(Atomic, O_EXCL); #undef if_FLAGGED_SET - if (TemporaryFileName.empty() == false) - iFd = open(TemporaryFileName.c_str(), fileflags, Perms); + if ((Mode & Atomic) == Atomic) + { + char *name = strdup((FileName + ".XXXXXX").c_str()); + + if((iFd = mkostemp(name, fileflags)) == -1) + { + free(name); + return FileFdErrno("mkostemp", "Could not create temporary file for %s", FileName.c_str()); + } + + TemporaryFileName = string(name); + + if(fchmod(iFd, Perms) == -1) + { + free(name); + return FileFdErrno("fchmod", "Could not assign permissions to temporary file %s with error %s", FileName.c_str(), strerror(errno)); + } + free(name); + } else iFd = open(FileName.c_str(), fileflags, Perms); -- cgit v1.2.3 From dc545c0bcd252bca491d0c669adddb5d62390a15 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 27 Aug 2013 21:50:22 +0200 Subject: use mkstemp instead of mkostemp in FileFd::Open() FileFd currently supports no fileflags which would make sense to provide via mkostemp, so we can just use mkstemp here which is a standard function compared to glib extension mkostemp. O_CREAT (Create) and O_TRUNC (Empty) are implied by O_EXCL, which is the mode mkstemp uses by default. The file description is opened ReadWrite, but that used to be the default for FileFd in the old times and not a problem as the difference is needed by FileFd to decide in which way the compressor pipeline needs to be created (if any). Git-Dch: Ignore --- apt-pkg/contrib/fileutl.cc | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 3eeef58cf..4806ae3f9 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -968,27 +968,23 @@ bool FileFd::Open(string FileName,unsigned int const Mode,APT::Configuration::Co if_FLAGGED_SET(Create, O_CREAT); if_FLAGGED_SET(Empty, O_TRUNC); if_FLAGGED_SET(Exclusive, O_EXCL); - else if_FLAGGED_SET(Atomic, O_EXCL); #undef if_FLAGGED_SET if ((Mode & Atomic) == Atomic) { char *name = strdup((FileName + ".XXXXXX").c_str()); - if((iFd = mkostemp(name, fileflags)) == -1) + if((iFd = mkstemp(name)) == -1) { free(name); return FileFdErrno("mkostemp", "Could not create temporary file for %s", FileName.c_str()); } TemporaryFileName = string(name); - - if(fchmod(iFd, Perms) == -1) - { - free(name); - return FileFdErrno("fchmod", "Could not assign permissions to temporary file %s with error %s", FileName.c_str(), strerror(errno)); - } free(name); + + if(Perms != 600 && fchmod(iFd, Perms) == -1) + return FileFdErrno("fchmod", "Could not change permissions for temporary file %s", TemporaryFileName.c_str()); } else iFd = open(FileName.c_str(), fileflags, Perms); -- cgit v1.2.3 From 98b69f9dd0ced02b01e276041635c7bb7f2484e3 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Sat, 31 Aug 2013 17:05:23 +0200 Subject: fix typo (mkostemp->mkstemp) --- apt-pkg/contrib/fileutl.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 4806ae3f9..3966eb0ed 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -977,7 +977,7 @@ bool FileFd::Open(string FileName,unsigned int const Mode,APT::Configuration::Co if((iFd = mkstemp(name)) == -1) { free(name); - return FileFdErrno("mkostemp", "Could not create temporary file for %s", FileName.c_str()); + return FileFdErrno("mkstemp", "Could not create temporary file for %s", FileName.c_str()); } TemporaryFileName = string(name); -- cgit v1.2.3 From 00f4d9ffa3468e899abf8fbda8db71fc3143b8e5 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Sat, 7 Sep 2013 12:19:51 +0200 Subject: implement StringSplit() as we need this to fix the dpkg status-fd output parsing --- apt-pkg/contrib/strutl.cc | 22 ++++++++++++++++++++++ apt-pkg/contrib/strutl.h | 2 ++ 2 files changed, 24 insertions(+) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index 0955b69f7..819d50de0 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -1118,6 +1118,28 @@ vector VectorizeString(string const &haystack, char const &split) return exploded; } /*}}}*/ +// StringSplit - like python string.split /*{{{*/ +// --------------------------------------------------------------------- +/* This can be used to split a given string up into a vector of strings + * The seperator is a string + */ +vector StringSplit(string const &s, std::string const &sep) +{ + vector split; + size_t start, pos; + start = pos = 0; + if(sep.size() == 0) + return split; + + do { + pos = s.find(sep, start); + split.push_back(s.substr(start, pos-start)); + if(pos != string::npos) + start = pos+sep.size(); + } while (pos != string::npos); + return split; +} + /*}}}*/ // RegexChoice - Simple regex list/list matcher /*{{{*/ // --------------------------------------------------------------------- /* */ diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h index 530896141..c97246c90 100644 --- a/apt-pkg/contrib/strutl.h +++ b/apt-pkg/contrib/strutl.h @@ -65,6 +65,8 @@ bool Hex2Num(const std::string &Str,unsigned char *Num,unsigned int Length); bool TokSplitString(char Tok,char *Input,char **List, unsigned long ListMax); std::vector VectorizeString(std::string const &haystack, char const &split) __attrib_const; +// like python string.split +std::vector StringSplit(std::string const &haystack, std::string const &sep) __attrib_const; void ioprintf(std::ostream &out,const char *format,...) __like_printf(2); void strprintf(std::string &out,const char *format,...) __like_printf(2); char *safe_snprintf(char *Buffer,char *End,const char *Format,...) __like_printf(3); -- cgit v1.2.3 From 85bf001994fa59ca979293af3abb89d3486e0afb Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Sat, 7 Sep 2013 13:12:50 +0200 Subject: add maxsplit parameter to StringSplit --- apt-pkg/contrib/strutl.cc | 18 +++++++++++++----- apt-pkg/contrib/strutl.h | 2 +- 2 files changed, 14 insertions(+), 6 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index 819d50de0..508af8922 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -1123,19 +1123,27 @@ vector VectorizeString(string const &haystack, char const &split) /* This can be used to split a given string up into a vector of strings * The seperator is a string */ -vector StringSplit(string const &s, std::string const &sep) +vector StringSplit(string const &s, std::string const &sep, + unsigned int maxsplit) { vector split; size_t start, pos; - start = pos = 0; + if(sep.size() == 0) return split; - + + start = pos = 0; do { pos = s.find(sep, start); split.push_back(s.substr(start, pos-start)); - if(pos != string::npos) - start = pos+sep.size(); + + // deal with the max-split + if(maxsplit > 0 && split.size() >= maxsplit) + { + split[split.size()-1] = s.substr(start); + break; + } + start = pos+sep.size(); } while (pos != string::npos); return split; } diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h index c97246c90..944f91403 100644 --- a/apt-pkg/contrib/strutl.h +++ b/apt-pkg/contrib/strutl.h @@ -66,7 +66,7 @@ bool TokSplitString(char Tok,char *Input,char **List, unsigned long ListMax); std::vector VectorizeString(std::string const &haystack, char const &split) __attrib_const; // like python string.split -std::vector StringSplit(std::string const &haystack, std::string const &sep) __attrib_const; +std::vector StringSplit(std::string const &haystack, std::string const &sep, unsigned int maxsplit=0) __attrib_const; void ioprintf(std::ostream &out,const char *format,...) __like_printf(2); void strprintf(std::string &out,const char *format,...) __like_printf(2); char *safe_snprintf(char *Buffer,char *End,const char *Format,...) __like_printf(3); -- cgit v1.2.3 From cd4ee27de851910dd84067c45d487c5460641913 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Sat, 7 Sep 2013 13:30:48 +0200 Subject: fix multiarch status-fd progress calculation --- apt-pkg/deb/dpkgpm.cc | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 3c1013761..d935eb07d 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -512,7 +512,8 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) /* dpkg sends strings like this: - 'status: : ' + 'status: : ' + 'status: :: ' errors look like this: 'status: /var/cache/apt/archives/krecipes_0.8.1-0ubuntu1_i386.deb : error : trying to overwrite `/usr/share/doc/kde/HTML/en/krecipes/krectip.png', which is also in package krecipes-data and conffile-prompt like this @@ -527,29 +528,36 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) 'processing: trigproc: trigger' */ - char* list[6]; - // dpkg sends multiline error messages sometimes (see - // #374195 for a example. we should support this by - // either patching dpkg to not send multiline over the - // statusfd or by rewriting the code here to deal with - // it. for now we just ignore it and not crash - TokSplitString(':', line, list, sizeof(list)/sizeof(list[0])); - if( list[0] == NULL || list[1] == NULL || list[2] == NULL) + // we need to split on ": " (note the appended space) as the ':' is + // part of the pkgname:arch information that dpkg sends + // + // A dpkg error message may contain additional ":" (like + // "failed in buffer_write(fd) (10, ret=-1): backend dpkg-deb ..." + // so we need to ensure to not split too much + std::vector list = StringSplit(line, ": ", 3); + if(list.size() != 3) { if (Debug == true) std::clog << "ignoring line: not enough ':'" << std::endl; return; } - const char* const pkg = list[1]; - const char* action = _strstrip(list[2]); + // dpkg does not send always send "pkgname:arch" so we add it here if needed + std::string pkgname = list[1]; + if (pkgname.find(":") == std::string::npos) + { + string const nativeArch = _config->Find("APT::Architecture"); + pkgname = pkgname + ":" + nativeArch; + } + const char* const pkg = pkgname.c_str(); + const char* action = list[2].c_str(); // 'processing' from dpkg looks like // 'processing: action: pkg' - if(strncmp(list[0], "processing", strlen("processing")) == 0) + if(strncmp(list[0].c_str(), "processing", strlen("processing")) == 0) { char s[200]; - const char* const pkg_or_trigger = _strstrip(list[2]); - action = _strstrip( list[1]); + const char* const pkg_or_trigger = list[2].c_str(); + action = list[1].c_str(); const std::pair * const iter = std::find_if(PackageProcessingOpsBegin, PackageProcessingOpsEnd, @@ -578,14 +586,6 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) if(strncmp(action,"error",strlen("error")) == 0) { - // urgs, sometime has ":" in its error string so that we - // end up with the error message split between list[3] - // and list[4], e.g. the message: - // "failed in buffer_write(fd) (10, ret=-1): backend dpkg-deb ..." - // concat them again - if( list[4] != NULL ) - list[3][strlen(list[3])] = ':'; - status << "pmerror:" << list[1] << ":" << (PackagesDone/float(PackagesTotal)*100.0) << ":" << list[3] @@ -595,7 +595,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) if (Debug == true) std::clog << "send: '" << status.str() << "'" << endl; pkgFailures++; - WriteApportReport(list[1], list[3]); + WriteApportReport(list[1].c_str(), list[3].c_str()); return; } else if(strncmp(action,"conffile",strlen("conffile")) == 0) @@ -1035,7 +1035,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) if((*I).Pkg.end() == true) continue; - string const name = (*I).Pkg.Name(); + string const name = (*I).Pkg.FullName(); PackageOpsDone[name] = 0; for(int i=0; (DpkgStatesOpMap[(*I).Op][i]).state != NULL; ++i) { -- cgit v1.2.3 From 9572a54bbc96eb653b3e13260abb183ba7a316f3 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Sat, 7 Sep 2013 16:16:49 +0200 Subject: doc update --- apt-pkg/contrib/strutl.cc | 15 +++++++++------ apt-pkg/contrib/strutl.h | 10 ++++++++-- 2 files changed, 17 insertions(+), 8 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index 508af8922..fd768f183 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -1118,10 +1118,11 @@ vector VectorizeString(string const &haystack, char const &split) return exploded; } /*}}}*/ -// StringSplit - like python string.split /*{{{*/ +// StringSplit - split a string into a string vector by token /*{{{*/ // --------------------------------------------------------------------- -/* This can be used to split a given string up into a vector of strings - * The seperator is a string +/* This can be used to split a given string up from a given string token + * into a vector of strings. A optional "maxsplit" argument can be used + * to limit the splitting, in this case the */ vector StringSplit(string const &s, std::string const &sep, unsigned int maxsplit) @@ -1129,22 +1130,24 @@ vector StringSplit(string const &s, std::string const &sep, vector split; size_t start, pos; + // no seperator given, this is bogus if(sep.size() == 0) return split; start = pos = 0; - do { + while (pos != string::npos) + { pos = s.find(sep, start); split.push_back(s.substr(start, pos-start)); - // deal with the max-split + // if maxsplit is reached, the remaining string is the last item if(maxsplit > 0 && split.size() >= maxsplit) { split[split.size()-1] = s.substr(start); break; } start = pos+sep.size(); - } while (pos != string::npos); + } return split; } /*}}}*/ diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h index 944f91403..080f9f82e 100644 --- a/apt-pkg/contrib/strutl.h +++ b/apt-pkg/contrib/strutl.h @@ -62,11 +62,17 @@ bool StrToNum(const char *Str,unsigned long &Res,unsigned Len,unsigned Base = 0) bool StrToNum(const char *Str,unsigned long long &Res,unsigned Len,unsigned Base = 0); bool Base256ToNum(const char *Str,unsigned long &Res,unsigned int Len); bool Hex2Num(const std::string &Str,unsigned char *Num,unsigned int Length); + +// input changing string split 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) __attrib_const; -// like python string.split -std::vector StringSplit(std::string const &haystack, std::string const &sep, unsigned int maxsplit=0) __attrib_const; + +// split a given string by a string token +std::vector StringSplit(std::string const &input, std::string const &sep, unsigned int maxsplit=0) __attrib_const; + void ioprintf(std::ostream &out,const char *format,...) __like_printf(2); void strprintf(std::string &out,const char *format,...) __like_printf(2); char *safe_snprintf(char *Buffer,char *End,const char *Format,...) __like_printf(3); -- cgit v1.2.3 From 5985c230c8ac85fe2b2eb504b798377843bdc7cd Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 20 Sep 2013 13:34:22 +0200 Subject: do not trust FileFd::Eof() in pkgTagFile::Fill() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Eof check was added (by me of course) in 0aae6d14390193e25ab6d0fd49295bd7b131954f as part of a fix up ~a month ago (at DebConf). The idea was not that bad, but doesn't make that much sense either as this bit is set by the FileFd based on Actual as well, so this is basically doing the same check again – with the difference that the HitEof bit can still linger from a previous Read we did at the end of the file, but have seek'd away from it now. Combined with the length of entries, entry order and other not that easily controllable conditions you can be 'lucky' enough to hit this problem in a way which even visible (truncating of other fields might not be visible easily, like 'Tags' and others). Closes: 723705 Thanks: Cyril Brulebois --- apt-pkg/tagfile.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc index b91e868e2..e0802e3d5 100644 --- a/apt-pkg/tagfile.cc +++ b/apt-pkg/tagfile.cc @@ -164,7 +164,7 @@ bool pkgTagFile::Fill() unsigned long long const dataSize = d->Size - ((d->End - d->Buffer) + 1); if (d->Fd.Read(d->End, dataSize, &Actual) == false) return false; - if (Actual != dataSize || d->Fd.Eof() == true) + if (Actual != dataSize) d->Done = true; d->End += Actual; } -- cgit v1.2.3 From b4140ecf132d15adf740f23330054b6788d4f9a6 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 21 Sep 2013 14:23:02 +0200 Subject: don't strip :any from dependencies in single-arch The parser goes a bit to far by stripping :any from dependencies in a single architecture environment. the flag "Multi-Arch: allowed" doesn't care any architecture restrictions in that case (as in single arch everything is native), but it still limits the possible versions statisfying the dependency so stripping :any over-simplifies in upgrade situations from "Multi-Arch: none" to "Multi-Arch: allowed". Closes: 723586 --- apt-pkg/deb/deblistparser.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 87aab6ee2..68d544e1f 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -635,7 +635,7 @@ bool debListParser::ParseDepends(pkgCache::VerIterator &Ver, string Version; unsigned int Op; - Start = ParseDepends(Start,Stop,Package,Version,Op,false,!MultiArchEnabled); + Start = ParseDepends(Start, Stop, Package, Version, Op, false, false); if (Start == 0) return _error->Error("Problem parsing dependency %s",Tag); size_t const found = Package.rfind(':'); @@ -717,9 +717,7 @@ bool debListParser::ParseProvides(pkgCache::VerIterator &Ver) } } - if (MultiArchEnabled == false) - return true; - else if ((Ver->MultiArch & pkgCache::Version::Allowed) == pkgCache::Version::Allowed) + if ((Ver->MultiArch & pkgCache::Version::Allowed) == pkgCache::Version::Allowed) { string const Package = string(Ver.ParentPkg().Name()).append(":").append("any"); return NewProvidesAllArch(Ver, Package, Ver.VerStr()); -- cgit v1.2.3 From 6c34cccad778bd8db0ce03b7596cbef03afa9688 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 26 Sep 2013 13:32:49 +0200 Subject: pkg from only trusted sources keeps being trusted --allow-unauthenticated switches the download to a pre-0.6 system in which a package can come from any source, rather than that trusted packages can only come from trusted sources. To allow this the flag used to set all packages as untrusted, which is a bit much, so we check now if the package can be acquired via an untrusted source and only if this is the case set it as untrusted. As APT nowadays supports setting sources as trusted via a flag in the sources.list this mode shouldn't be used that much anymore though. [Note that this is not the patch from the BTS] Closes: 617690 --- apt-pkg/acquire-item.cc | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 97b2d1e29..222b78671 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -1719,27 +1719,34 @@ pkgAcqArchive::pkgAcqArchive(pkgAcquire *Owner,pkgSourceList *Sources, } // check if we have one trusted source for the package. if so, switch - // to "TrustedOnly" mode + // to "TrustedOnly" mode - but only if not in AllowUnauthenticated mode + bool const allowUnauth = _config->FindB("APT::Get::AllowUnauthenticated", false); + bool const debugAuth = _config->FindB("Debug::pkgAcquire::Auth", false); + bool seenUntrusted = false; for (pkgCache::VerFileIterator i = Version.FileList(); i.end() == false; ++i) { pkgIndexFile *Index; if (Sources->FindIndex(i.File(),Index) == false) continue; - if (_config->FindB("Debug::pkgAcquire::Auth", false)) - { + + if (debugAuth == true) std::cerr << "Checking index: " << Index->Describe() - << "(Trusted=" << Index->IsTrusted() << ")\n"; - } - if (Index->IsTrusted()) { + << "(Trusted=" << Index->IsTrusted() << ")" << std::endl; + + if (Index->IsTrusted() == true) + { Trusted = true; - break; + if (allowUnauth == false) + break; } + else + seenUntrusted = true; } // "allow-unauthenticated" restores apts old fetching behaviour // that means that e.g. unauthenticated file:// uris are higher // priority than authenticated http:// uris - if (_config->FindB("APT::Get::AllowUnauthenticated",false) == true) + if (allowUnauth == true && seenUntrusted == true) Trusted = false; // Select a source -- cgit v1.2.3 From 8fa042ca39dcb39d544f015f4a924c5dbc10ad2c Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 30 Sep 2013 18:51:40 +0200 Subject: don't consider holds for autoremoval MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can't remove packages which are held back by the user with a hold, so marking them (or its dependencies) as garbage will lead our autoremover into madness – and given that the package is important enough that the user has held it back it can't be garbage (at least at the moment), so even if a front-end wants to use the info just for information display its a good idea to not consider it garbage for them. Closes: 724995 --- apt-pkg/depcache.cc | 7 ++++--- apt-pkg/depcache.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 978a893f7..a06789cdf 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -896,6 +896,7 @@ char const* PrintMode(char const mode) case pkgDepCache::ModeInstall: return "Install"; case pkgDepCache::ModeKeep: return "Keep"; case pkgDepCache::ModeDelete: return "Delete"; + case pkgDepCache::ModeGarbage: return "Garbage"; default: return "UNKNOWN"; } } @@ -1726,8 +1727,6 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc) follow_recommends = MarkFollowsRecommends(); follow_suggests = MarkFollowsSuggests(); - - // do the mark part, this is the core bit of the algorithm for(PkgIterator p = PkgBegin(); !p.end(); ++p) { @@ -1738,7 +1737,9 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc) // be nice even then a required package violates the policy (#583517) // and do the full mark process also for required packages (p.CurrentVer().end() != true && - p.CurrentVer()->Priority == pkgCache::State::Required)) + p.CurrentVer()->Priority == pkgCache::State::Required) || + // packages which can't be changed (like holds) can't be garbage + (IsModeChangeOk(ModeGarbage, p, 0, false) == false)) { // the package is installed (and set to keep) if(PkgState[p->ID].Keep() && !p.CurrentVer().end()) diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h index d9c95349b..61c9aa559 100644 --- a/apt-pkg/depcache.h +++ b/apt-pkg/depcache.h @@ -128,7 +128,7 @@ class pkgDepCache : protected pkgCache::Namespace enum InternalFlags {AutoKept = (1 << 0), Purge = (1 << 1), ReInstall = (1 << 2), Protected = (1 << 3)}; enum VersionTypes {NowVersion, InstallVersion, CandidateVersion}; - enum ModeList {ModeDelete = 0, ModeKeep = 1, ModeInstall = 2}; + enum ModeList {ModeDelete = 0, ModeKeep = 1, ModeInstall = 2, ModeGarbage = 3}; /** \brief Represents an active action group. * -- cgit v1.2.3 From 41053d721ce7f81652d7e873067376b94f9a060d Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 1 Oct 2013 12:03:37 +0200 Subject: improve documentation for StringSplit() --- apt-pkg/contrib/strutl.cc | 6 ++---- apt-pkg/contrib/strutl.h | 19 +++++++++++++++++-- 2 files changed, 19 insertions(+), 6 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index fd768f183..96c6d2f35 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -1120,11 +1120,9 @@ vector VectorizeString(string const &haystack, char const &split) /*}}}*/ // StringSplit - split a string into a string vector by token /*{{{*/ // --------------------------------------------------------------------- -/* This can be used to split a given string up from a given string token - * into a vector of strings. A optional "maxsplit" argument can be used - * to limit the splitting, in this case the +/* See header for details. */ -vector StringSplit(string const &s, std::string const &sep, +vector StringSplit(std::string const &s, std::string const &sep, unsigned int maxsplit) { vector split; diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h index 080f9f82e..eb47287a4 100644 --- a/apt-pkg/contrib/strutl.h +++ b/apt-pkg/contrib/strutl.h @@ -70,8 +70,23 @@ bool TokSplitString(char Tok,char *Input,char **List, // split a given string by a char std::vector VectorizeString(std::string const &haystack, char const &split) __attrib_const; -// split a given string by a string token -std::vector StringSplit(std::string const &input, std::string const &sep, unsigned int maxsplit=0) __attrib_const; +/* \brief Return a vector of strings from string "input" where "sep" + * is used as the delimiter string. + * + * \param input The input string. + * + * \param sep The seperator to use. + * + * \param maxsplit (optional) The maximum amount of splitting that + * should be done . + * + * The optional "maxsplit" argument can be used to limit the splitting, + * if used the string is only split on maxsplit places and the last + * item in the vector contains the remainder string. + */ +std::vector StringSplit(std::string const &input, + std::string const &sep, + unsigned int maxsplit=0) __attrib_const; void ioprintf(std::ostream &out,const char *format,...) __like_printf(2); void strprintf(std::string &out,const char *format,...) __like_printf(2); -- cgit v1.2.3 From 2ddab3fb958518acbd26685eeeb7755106b721a3 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 1 Oct 2013 12:38:03 +0200 Subject: change maxsplit default from "0" to maxint --- apt-pkg/contrib/strutl.cc | 2 +- apt-pkg/contrib/strutl.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index 96c6d2f35..77e48962c 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -1139,7 +1139,7 @@ vector StringSplit(std::string const &s, std::string const &sep, split.push_back(s.substr(start, pos-start)); // if maxsplit is reached, the remaining string is the last item - if(maxsplit > 0 && split.size() >= maxsplit) + if(split.size() >= maxsplit) { split[split.size()-1] = s.substr(start); break; diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h index eb47287a4..b42e06491 100644 --- a/apt-pkg/contrib/strutl.h +++ b/apt-pkg/contrib/strutl.h @@ -17,7 +17,7 @@ #define STRUTL_H - +#include #include #include #include @@ -86,7 +86,7 @@ std::vector VectorizeString(std::string const &haystack, char const */ std::vector StringSplit(std::string const &input, std::string const &sep, - unsigned int maxsplit=0) __attrib_const; + unsigned int maxsplit=std::numeric_limits::max()) __attrib_const; void ioprintf(std::ostream &out,const char *format,...) __like_printf(2); void strprintf(std::string &out,const char *format,...) __like_printf(2); -- cgit v1.2.3 From a38e023c9d5a237ccae1755966adc7c0bbdb9d7e Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Wed, 2 Oct 2013 10:15:28 +0200 Subject: make dpkg progress slightly nicer --- apt-pkg/deb/dpkgpm.cc | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index d935eb07d..a5097a04f 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -52,7 +53,8 @@ class pkgDPkgPMPrivate { public: pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0), - term_out(NULL), history_out(NULL) + term_out(NULL), history_out(NULL), + last_reported_progress(0.0) { dpkgbuf[0] = '\0'; } @@ -63,6 +65,8 @@ public: FILE *term_out; FILE *history_out; string dpkg_error; + + float last_reported_progress; }; namespace @@ -883,10 +887,16 @@ bool pkgDPkgPM::CloseLog() */ void pkgDPkgPM::SendTerminalProgress(float percentage) { + int reporting_steps = _config->FindI("DpkgPM::Reporting-Steps", 1); + + if(percentage < (d->last_reported_progress + reporting_steps)) + return; + // FIXME: use colors too std::cout << "\r\n" - << "Progress: [" << percentage << "%]" + << "Progress: [" << std::setw(3) << int(percentage) << "%]" << "\r\n"; + d->last_reported_progress = percentage; } /*}}}*/ /*{{{*/ @@ -1444,7 +1454,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) tcsetattr(0, TCSAFLUSH, &tt); close(master); } - + // Check for an error code. if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0) { @@ -1474,6 +1484,10 @@ bool pkgDPkgPM::Go(int OutStatusFd) } } CloseLog(); + + // dpkg is done at this point + if(_config->FindB("DPkgPM::Progress", false) == true) + SendTerminalProgress(100); if (pkgPackageManager::SigINTStop) _error->Warning(_("Operation was interrupted before it could finish")); -- cgit v1.2.3 From 3c8030a4977536e9d3a1954adc68082ae1c6d5a2 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 3 Oct 2013 01:12:18 +0200 Subject: refactor onError relabeling of DestFile as '.FAILED' This helps ensure three things: - each error is reported via ReportMirrorFailure - if DestFile doesn't exist, do not attempt rename - renames happen for every error The last one wasn't the case for Size mismatches, which isn't nice, but not a exploitable problem per-se as the file isn't picked up and remains in partial/ where the following download-try will at most take it for a partial request which fails the hashsum verification later on Git-Dch: Ignore --- apt-pkg/acquire-item.cc | 75 ++++++++++++++++++++++++++++--------------------- apt-pkg/acquire-item.h | 19 +++++++++++-- 2 files changed, 60 insertions(+), 34 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 222b78671..fcc7c7404 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -143,6 +143,32 @@ void pkgAcquire::Item::Rename(string From,string To) } } /*}}}*/ +bool pkgAcquire::Item::RenameOnError(pkgAcquire::Item::RenameOnErrorState const error)/*{{{*/ +{ + if(FileExists(DestFile)) + Rename(DestFile, DestFile + ".FAILED"); + + switch (error) + { + case HashSumMismatch: + ErrorText = _("Hash Sum mismatch"); + Status = StatAuthError; + ReportMirrorFailure("HashChecksumFailure"); + break; + case SizeMismatch: + ErrorText = _("Size mismatch"); + Status = StatAuthError; + ReportMirrorFailure("SizeFailure"); + break; + case InvalidFormat: + ErrorText = _("Invalid file format"); + Status = StatError; + // do not report as usually its not the mirrors fault, but Portal/Proxy + break; + } + return false; +} + /*}}}*/ // Acquire::Item::ReportMirrorFailure /*{{{*/ // --------------------------------------------------------------------- void pkgAcquire::Item::ReportMirrorFailure(string FailCode) @@ -595,9 +621,7 @@ void pkgAcqIndexDiffs::Finish(bool allDone) if(!ExpectedHash.empty() && !ExpectedHash.VerifyFile(DestFile)) { - Status = StatAuthError; - ErrorText = _("MD5Sum mismatch"); - Rename(DestFile,DestFile + ".FAILED"); + RenameOnError(HashSumMismatch); Dequeue(); return; } @@ -866,10 +890,7 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,string Hash, if (!ExpectedHash.empty() && ExpectedHash.toStr() != Hash) { - Status = StatAuthError; - ErrorText = _("Hash Sum mismatch"); - Rename(DestFile,DestFile + ".FAILED"); - ReportMirrorFailure("HashChecksumFailure"); + RenameOnError(HashSumMismatch); return; } @@ -878,22 +899,18 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,string Hash, if (Verify == true) { FileFd fd(DestFile, FileFd::ReadOnly); - pkgTagSection sec; - pkgTagFile tag(&fd); - - // Only test for correctness if the file is not empty (empty is ok) - if (fd.Size() > 0) { - if (_error->PendingError() || !tag.Step(sec)) { - Status = StatError; - _error->DumpErrors(); - Rename(DestFile,DestFile + ".FAILED"); - return; - } else if (!sec.Exists("Package")) { - Status = StatError; - ErrorText = ("Encountered a section with no Package: header"); - Rename(DestFile,DestFile + ".FAILED"); - return; - } + // Only test for correctness if the file is not empty (empty is ok) + if (fd.FileSize() > 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) + { + RenameOnError(InvalidFormat); + return; + } } } @@ -1907,18 +1924,14 @@ void pkgAcqArchive::Done(string Message,unsigned long long Size,string CalcHash, // Check the size if (Size != Version->Size) { - Status = StatError; - ErrorText = _("Size mismatch"); + RenameOnError(SizeMismatch); return; } // Check the hash if(ExpectedHash.toStr() != CalcHash) { - Status = StatError; - ErrorText = _("Hash Sum mismatch"); - if(FileExists(DestFile)) - Rename(DestFile,DestFile + ".FAILED"); + RenameOnError(HashSumMismatch); return; } @@ -2058,9 +2071,7 @@ void pkgAcqFile::Done(string Message,unsigned long long Size,string CalcHash, // Check the hash if(!ExpectedHash.empty() && ExpectedHash.toStr() != CalcHash) { - Status = StatError; - ErrorText = _("Hash Sum mismatch"); - Rename(DestFile,DestFile + ".FAILED"); + RenameOnError(HashSumMismatch); return; } diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index 10c855e63..6b4f73708 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -83,7 +83,7 @@ class pkgAcquire::Item : public WeakPointable * overwritten. */ void Rename(std::string From,std::string To); - + public: /** \brief The current status of this item. */ @@ -281,6 +281,21 @@ class pkgAcquire::Item : public WeakPointable * pkgAcquire::Remove. */ virtual ~Item(); + + protected: + + enum RenameOnErrorState { + HashSumMismatch, + SizeMismatch, + InvalidFormat + }; + + /** \brief Rename failed file and set error + * + * \param state respresenting the error we encountered + * \param errorMsg a message describing the error + */ + bool RenameOnError(RenameOnErrorState const state); }; /*}}}*/ /** \brief Information about an index patch (aka diff). */ /*{{{*/ @@ -982,7 +997,7 @@ class pkgAcqArchive : public pkgAcquire::Item * * \param Version The package version to download. * - * \param StoreFilename A location in which the actual filename of + * \param[out] StoreFilename A location in which the actual filename of * the package should be stored. It will be set to a guessed * basename in the constructor, and filled in with a fully * qualified filename once the download finishes. -- cgit v1.2.3 From d57f6084aaa3972073114973d149ea2291b36682 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 3 Oct 2013 15:11:21 +0200 Subject: use pkgAcqArchive in 'download' for proper errors With a bit of trickery we can reuse the usual infrastructure we have in place to acquire deb files for the 'download' operation as well, which gains us authentification check & display, error messages, correct filenames and "downloads" from the root-owned archives. --- apt-pkg/acquire-item.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index fcc7c7404..04505b35a 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -1768,9 +1768,8 @@ pkgAcqArchive::pkgAcqArchive(pkgAcquire *Owner,pkgSourceList *Sources, // Select a source if (QueueNext() == false && _error->PendingError() == false) - _error->Error(_("I wasn't able to locate a file for the %s package. " - "This might mean you need to manually fix this package."), - Version.ParentPkg().Name()); + _error->Error(_("Can't find a source to download version '%s' of '%s'"), + Version.VerStr(), Version.ParentPkg().FullName(false).c_str()); } /*}}}*/ // AcqArchive::QueueNext - Queue the next file source /*{{{*/ -- cgit v1.2.3 From 342df712331004aa4907c9dbdf4b7728d087efb0 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 3 Oct 2013 21:34:52 +0200 Subject: fix lzma-support detection via xz binary Clear() only clears a config option, not removing it and an empty setting still exists. Hence we set the option instead to the xz path so that the later existance check can find a binary for the test --- apt-pkg/aptconfiguration.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/aptconfiguration.cc b/apt-pkg/aptconfiguration.cc index 4f9b84e00..115d11616 100644 --- a/apt-pkg/aptconfiguration.cc +++ b/apt-pkg/aptconfiguration.cc @@ -453,7 +453,7 @@ void Configuration::setDefaultConfigurationForCompressors() { _config->CndSet("Dir::Bin::bzip2", "/bin/bzip2"); _config->CndSet("Dir::Bin::xz", "/usr/bin/xz"); if (FileExists(_config->FindFile("Dir::Bin::xz")) == true) { - _config->Clear("Dir::Bin::lzma"); + _config->Set("Dir::Bin::lzma", _config->FindFile("Dir::Bin::xz")); _config->Set("APT::Compressor::lzma::Binary", "xz"); if (_config->Exists("APT::Compressor::lzma::CompressArg") == false) { _config->Set("APT::Compressor::lzma::CompressArg::", "--format=lzma"); -- cgit v1.2.3 From af6b41692b21a7fd1561d9ad4b3e4407ab93246f Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 7 Oct 2013 10:26:50 +0200 Subject: add -o DpkgPM::Progress-Fancy for better dpkg progress output on vt100+ terminals --- apt-pkg/deb/dpkgpm.cc | 88 +++++++++++++++++++++++++++++++++++++++++++++------ apt-pkg/deb/dpkgpm.h | 2 ++ 2 files changed, 81 insertions(+), 9 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index a5097a04f..4eb373fb7 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -54,9 +54,15 @@ class pkgDPkgPMPrivate public: pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0), term_out(NULL), history_out(NULL), - last_reported_progress(0.0) + last_reported_progress(0.0), nr_terminal_rows(0), + fancy_progress_output(false) { dpkgbuf[0] = '\0'; + if(_config->FindB("DpkgPM::Progress-Fancy", false)) + { + fancy_progress_output = true; + _config->Set("DpkgPM::Progress", true); + } } bool stdin_is_dev_null; // the buffer we use for the dpkg status-fd reading @@ -67,6 +73,8 @@ public: string dpkg_error; float last_reported_progress; + int nr_terminal_rows; + bool fancy_progress_output; }; namespace @@ -892,10 +900,37 @@ void pkgDPkgPM::SendTerminalProgress(float percentage) if(percentage < (d->last_reported_progress + reporting_steps)) return; - // FIXME: use colors too - std::cout << "\r\n" - << "Progress: [" << std::setw(3) << int(percentage) << "%]" - << "\r\n"; + std::string progress_str; + strprintf(progress_str, "Progress: [%3i%%]", (int)percentage); + if (d->fancy_progress_output) + { + int row = d->nr_terminal_rows; + + static string save_cursor = "\033[s"; + static string restore_cursor = "\033[u"; + + static string set_bg_color = "\033[42m"; // green + static string set_fg_color = "\033[30m"; // black + + static string restore_bg = "\033[49m"; + static string restore_fg = "\033[39m"; + + std::cout << save_cursor + // move cursor position to last row + << "\033[" << row << ";0f" + << set_bg_color + << set_fg_color + << progress_str + << restore_cursor + << restore_bg + << restore_fg; + } + else + { + std::cout << progress_str << "\r\n"; + } + std::flush(std::cout); + d->last_reported_progress = percentage; } /*}}}*/ @@ -920,6 +955,29 @@ static int racy_pselect(int nfds, fd_set *readfds, fd_set *writefds, return retval; } /*}}}*/ + +void pkgDPkgPM::SetupTerminalScrollArea(int nr_rows) +{ + if(!d->fancy_progress_output) + return; + + // scroll down a bit to avoid visual glitch when the screen + // area shrinks by one row + std::cout << "\n\n"; + + // save cursor + std::cout << "\033[s"; + + // set scroll region (this will place the cursor in the top left) + std::cout << "\033[1;" << nr_rows - 1 << "r"; + + // restore cursor but ensure its inside the scrolling area + std::cout << "\033[u"; + static const char *move_cursor_up = "\033[1A"; + std::cout << move_cursor_up; + std::flush(std::cout); +} + // DPkgPM::Go - Run the sequence /*{{{*/ // --------------------------------------------------------------------- /* This globs the operations and calls dpkg @@ -1276,7 +1334,8 @@ bool pkgDPkgPM::Go(int OutStatusFd) _error->PushToStack(); if (tcgetattr(STDOUT_FILENO, &tt) == 0) { - ioctl(0, TIOCGWINSZ, (char *)&win); + ioctl(1, TIOCGWINSZ, (char *)&win); + d->nr_terminal_rows = win.ws_row; if (openpty(&master, &slave, NULL, &tt, &win) < 0) { _error->Errno("openpty", _("Can not write log (%s)"), _("Is /dev/pts mounted?")); @@ -1318,11 +1377,12 @@ bool pkgDPkgPM::Go(int OutStatusFd) << endl; FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); } + Child = ExecFork(); - // This is the child if (Child == 0) { + if(slave >= 0 && master >= 0) { setsid(); @@ -1339,7 +1399,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) if (chdir(_config->FindDir("DPkg::Run-Directory","/").c_str()) != 0) _exit(100); - + if (_config->FindB("DPkg::FlushSTDIN",true) == true && isatty(STDIN_FILENO)) { int Flags,dummy; @@ -1355,6 +1415,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) if (fcntl(STDIN_FILENO,F_SETFL,Flags & (~(long)O_NONBLOCK)) < 0) _exit(100); } + SetupTerminalScrollArea(d->nr_terminal_rows); /* No Job Control Stop Env is a magic dpkg var that prevents it from using sigstop */ @@ -1449,6 +1510,15 @@ bool pkgDPkgPM::Go(int OutStatusFd) signal(SIGHUP,old_SIGHUP); + // reset scroll area + SetupTerminalScrollArea(d->nr_terminal_rows); + if(d->fancy_progress_output) + { + // override the progress line (sledgehammer) + static const char* clear_screen_below_cursor = "\033[J"; + std::cout << clear_screen_below_cursor; + } + if(master >= 0) { tcsetattr(0, TCSAFLUSH, &tt); @@ -1488,7 +1558,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) // dpkg is done at this point if(_config->FindB("DPkgPM::Progress", false) == true) SendTerminalProgress(100); - + if (pkgPackageManager::SigINTStop) _error->Warning(_("Operation was interrupted before it could finish")); diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h index 29901a204..3b8d36623 100644 --- a/apt-pkg/deb/dpkgpm.h +++ b/apt-pkg/deb/dpkgpm.h @@ -84,6 +84,8 @@ class pkgDPkgPM : public pkgPackageManager bool SendPkgsInfo(FILE * const F, unsigned int const &Version); void WriteHistoryTag(std::string const &tag, std::string value); + // Terminal progress + void SetupTerminalScrollArea(int nr_scrolled_rows); void SendTerminalProgress(float percentage); // apport integration -- cgit v1.2.3 From 1c6089d72ddf59875fae4f281f023abba0d4fda0 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 7 Oct 2013 13:37:28 +0200 Subject: use Dpkg::Progress-Fancy to be consitent with Dpkg::Progress --- apt-pkg/deb/dpkgpm.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 4eb373fb7..a116db9cf 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -58,7 +58,7 @@ public: fancy_progress_output(false) { dpkgbuf[0] = '\0'; - if(_config->FindB("DpkgPM::Progress-Fancy", false)) + if(_config->FindB("Dpkg::Progress-Fancy", false) == true) { fancy_progress_output = true; _config->Set("DpkgPM::Progress", true); -- cgit v1.2.3 From 3286ad136cbfdb73b97f880ba1ad19a2000781c5 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 7 Oct 2013 13:42:50 +0200 Subject: fix libapt-inst for >2G debs (closes: #725483) --- apt-pkg/contrib/fileutl.cc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 3966eb0ed..0261119ba 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -656,9 +656,9 @@ string flNoLink(string File) while (1) { // Read the link - int Res; + ssize_t Res; if ((Res = readlink(NFile.c_str(),Buffer,sizeof(Buffer))) <= 0 || - (unsigned)Res >= sizeof(Buffer)) + (size_t)Res >= sizeof(Buffer)) return File; // Append or replace the previous path @@ -1244,7 +1244,7 @@ FileFd::~FileFd() gracefully. */ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual) { - int Res; + ssize_t Res; errno = 0; if (Actual != 0) *Actual = 0; @@ -1344,7 +1344,7 @@ char* FileFd::ReadLine(char *To, unsigned long long const Size) /* */ bool FileFd::Write(const void *From,unsigned long long Size) { - int Res; + ssize_t Res; errno = 0; do { @@ -1398,7 +1398,7 @@ bool FileFd::Write(const void *From,unsigned long long Size) } bool FileFd::Write(int Fd, const void *From, unsigned long long Size) { - int Res; + ssize_t Res; errno = 0; do { @@ -1471,14 +1471,14 @@ bool FileFd::Seek(unsigned long long To) d->seekpos = To; return true; } - int res; + off_t res; #ifdef HAVE_ZLIB if (d != NULL && d->gz) res = gzseek(d->gz,To,SEEK_SET); else #endif res = lseek(iFd,To,SEEK_SET); - if (res != (signed)To) + if (res != (off_t)To) return FileFdError("Unable to seek to %llu", To); if (d != NULL) @@ -1509,7 +1509,7 @@ bool FileFd::Skip(unsigned long long Over) return true; } - int res; + off_t res; #ifdef HAVE_ZLIB if (d != NULL && d->gz != NULL) res = gzseek(d->gz,Over,SEEK_CUR); -- cgit v1.2.3 From 28e3b6f6f822a640aec35a41d5e99a97cfa1e9b1 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 7 Oct 2013 13:46:30 +0200 Subject: fix off-by-one error in pkgDPkgPM::SetupTerminalScrollArea() --- apt-pkg/deb/dpkgpm.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index a116db9cf..7d8c9b4e0 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -963,7 +963,7 @@ void pkgDPkgPM::SetupTerminalScrollArea(int nr_rows) // scroll down a bit to avoid visual glitch when the screen // area shrinks by one row - std::cout << "\n\n"; + std::cout << "\n"; // save cursor std::cout << "\033[s"; -- cgit v1.2.3 From 77fdc2a4de43144432ef9e74058634e94e45ef65 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 8 Oct 2013 21:48:14 +0200 Subject: apt-pkg/deb/dpkgpm.cc: fix off-by-one in SetupTerminalScrollArea reset --- apt-pkg/deb/dpkgpm.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 7d8c9b4e0..b4d812d26 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1511,7 +1511,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) signal(SIGHUP,old_SIGHUP); // reset scroll area - SetupTerminalScrollArea(d->nr_terminal_rows); + SetupTerminalScrollArea(d->nr_terminal_rows + 1); if(d->fancy_progress_output) { // override the progress line (sledgehammer) -- cgit v1.2.3 From f28eef6df2a9fd2befedacf8ccd6248e5b3618db Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 11 Oct 2013 22:05:38 +0200 Subject: add missing _() around the new "Progress" string --- apt-pkg/deb/dpkgpm.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index b4d812d26..c29d21574 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -901,7 +901,7 @@ void pkgDPkgPM::SendTerminalProgress(float percentage) return; std::string progress_str; - strprintf(progress_str, "Progress: [%3i%%]", (int)percentage); + strprintf(progress_str, _("Progress: [%3i%%]"), (int)percentage); if (d->fancy_progress_output) { int row = d->nr_terminal_rows; -- cgit v1.2.3 From 7794a6880e74446075d9cae19525829ada5b0d91 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 13 Oct 2013 19:33:09 +0200 Subject: fix progress-segfault in case of dpkg errors/prompts Errors and conffile prompts have a fourth information piece, which the "old" code access which isn't provided by the "new" one. This isn't checking if the messages are really well-formed, so it could still segfault on misformed messages, but this code needs more work anyway, so one step at a time. Closes: 726047 --- 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 c29d21574..1fbeabbdc 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -546,8 +546,8 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) // A dpkg error message may contain additional ":" (like // "failed in buffer_write(fd) (10, ret=-1): backend dpkg-deb ..." // so we need to ensure to not split too much - std::vector list = StringSplit(line, ": ", 3); - if(list.size() != 3) + std::vector list = StringSplit(line, ": ", 4); + if(list.size() < 3) { if (Debug == true) std::clog << "ignoring line: not enough ':'" << std::endl; -- cgit v1.2.3 From fd6417a6026401f95af82608e12b4a9d105b090f Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 15 Oct 2013 15:39:59 +0200 Subject: fix logic for finding what package dpkg means in the --status-fd and only send out short packagenames --- apt-pkg/deb/dpkgpm.cc | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index b4d812d26..61d8eec02 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -557,11 +557,26 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) std::string pkgname = list[1]; if (pkgname.find(":") == std::string::npos) { - string const nativeArch = _config->Find("APT::Architecture"); - pkgname = pkgname + ":" + nativeArch; + // find the package in the group that is in a touched by dpkg + // if there are multiple dpkg will send us a full pkgname:arch + pkgCache::GrpIterator Grp = Cache.FindGrp(pkgname); + if (Grp.end() == false) + { + pkgCache::PkgIterator P = Grp.PackageList(); + for (; P.end() != true; P = Grp.NextPkg(P)) + { + if(Cache[P].Mode != pkgDepCache::ModeKeep) + { + pkgname = P.FullName(); + break; + } + } + } } const char* const pkg = pkgname.c_str(); const char* action = list[2].c_str(); + + std::string short_pkgname = StringSplit(pkgname, ":")[0]; // 'processing' from dpkg looks like // 'processing: action: pkg' @@ -640,7 +655,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) PackageOpsDone[pkg]++; PackagesDone++; // build the status str - status << "pmstatus:" << pkg + status << "pmstatus:" << short_pkgname << ":" << (PackagesDone/float(PackagesTotal)*100.0) << ":" << s << endl; @@ -653,7 +668,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) std::clog << "send: '" << status.str() << "'" << endl; } if (Debug == true) - std::clog << "(parsed from dpkg) pkg: " << pkg + std::clog << "(parsed from dpkg) pkg: " << short_pkgname << " action: " << action << endl; } /*}}}*/ -- cgit v1.2.3 From 42c1513b712818823e0a136c949f0d93c46907d7 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 15 Oct 2013 18:07:44 +0200 Subject: tests, do not send pkgname with arch via the status-fd --- apt-pkg/deb/dpkgpm.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index d18900b9c..fe38bf697 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -649,7 +649,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) // action const char *translation = _(states[PackageOpsDone[pkg]].str); char s[200]; - snprintf(s, sizeof(s), translation, pkg); + snprintf(s, sizeof(s), translation, short_pkgname.c_str()); // we moved from one dpkg state to a new one, report that PackageOpsDone[pkg]++; -- cgit v1.2.3 From c420fe0096985234e861aaafc2b9908b6259a1bb Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 17 Oct 2013 07:47:15 +0200 Subject: fix broken clean when apt was finished and ensure that terminal progress is updated when a new dpkg-loop is entered in dpkgpm.cc --- apt-pkg/deb/dpkgpm.cc | 28 +++++++++++++++++++--------- apt-pkg/deb/dpkgpm.h | 1 + 2 files changed, 20 insertions(+), 9 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index fe38bf697..f870fab93 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -993,6 +993,20 @@ void pkgDPkgPM::SetupTerminalScrollArea(int nr_rows) std::flush(std::cout); } +void pkgDPkgPM::CleanupTerminal() +{ + // reset scroll area + SetupTerminalScrollArea(d->nr_terminal_rows + 1); + if(d->fancy_progress_output) + { + // override the progress line (sledgehammer) + static const char* clear_screen_below_cursor = "\033[J"; + std::cout << clear_screen_below_cursor; + std::flush(std::cout); + } +} + + // DPkgPM::Go - Run the sequence /*{{{*/ // --------------------------------------------------------------------- /* This globs the operations and calls dpkg @@ -1430,7 +1444,9 @@ bool pkgDPkgPM::Go(int OutStatusFd) if (fcntl(STDIN_FILENO,F_SETFL,Flags & (~(long)O_NONBLOCK)) < 0) _exit(100); } + // setup terminal SetupTerminalScrollArea(d->nr_terminal_rows); + SendTerminalProgress(PackagesDone/float(PackagesTotal)*100.0); /* No Job Control Stop Env is a magic dpkg var that prevents it from using sigstop */ @@ -1525,15 +1541,6 @@ bool pkgDPkgPM::Go(int OutStatusFd) signal(SIGHUP,old_SIGHUP); - // reset scroll area - SetupTerminalScrollArea(d->nr_terminal_rows + 1); - if(d->fancy_progress_output) - { - // override the progress line (sledgehammer) - static const char* clear_screen_below_cursor = "\033[J"; - std::cout << clear_screen_below_cursor; - } - if(master >= 0) { tcsetattr(0, TCSAFLUSH, &tt); @@ -1564,6 +1571,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) if(stopOnError) { CloseLog(); + CleanupTerminal(); return false; } } @@ -1574,6 +1582,8 @@ bool pkgDPkgPM::Go(int OutStatusFd) if(_config->FindB("DPkgPM::Progress", false) == true) SendTerminalProgress(100); + CleanupTerminal(); + if (pkgPackageManager::SigINTStop) _error->Warning(_("Operation was interrupted before it could finish")); diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h index 3b8d36623..1a58e1af5 100644 --- a/apt-pkg/deb/dpkgpm.h +++ b/apt-pkg/deb/dpkgpm.h @@ -87,6 +87,7 @@ class pkgDPkgPM : public pkgPackageManager // Terminal progress void SetupTerminalScrollArea(int nr_scrolled_rows); void SendTerminalProgress(float percentage); + void CleanupTerminal(); // apport integration void WriteApportReport(const char *pkgpath, const char *errormsg); -- cgit v1.2.3 From 2842f8f3e31fbec8c53ce40f15ff0c76f021f030 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 18 Oct 2013 08:10:29 +0200 Subject: add APT::String::Strip(), start cleanup of ProcessDpkgStatusLine --- apt-pkg/contrib/strutl.cc | 17 ++++++++++++++++- apt-pkg/contrib/strutl.h | 7 +++++++ apt-pkg/deb/dpkgpm.cc | 33 ++++++++++++++++++++++++++++----- 3 files changed, 51 insertions(+), 6 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index 77e48962c..9f794927d 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -36,7 +36,22 @@ using namespace std; /*}}}*/ - +// Strip - Remove white space from the front and back of a string /*{{{*/ +// --------------------------------------------------------------------- +namespace APT { + namespace String { +std::string Strip(const std::string &s) +{ + size_t start = s.find_first_not_of(" \t\n"); + // only whitespace + if (start == string::npos) + return ""; + size_t end = s.find_last_not_of(" \t\n"); + return s.substr(start, end-start+1); +} +} +} + /*}}}*/ // UTF8ToCodeset - Convert some UTF-8 string for some codeset /*{{{*/ // --------------------------------------------------------------------- /* This is handy to use before display some information for enduser */ diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h index b42e06491..c8fc317c0 100644 --- a/apt-pkg/contrib/strutl.h +++ b/apt-pkg/contrib/strutl.h @@ -33,6 +33,13 @@ using std::vector; using std::ostream; #endif +namespace APT { + namespace String { + std::string Strip(const std::string &s); + }; +}; + + bool UTF8ToCodeset(const char *codeset, const std::string &orig, std::string *dest); char *_strstrip(char *String); char *_strrstrip(char *String); // right strip only diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index f870fab93..c5d40c033 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -540,6 +540,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) 'processing: trigproc: trigger' */ + // we need to split on ": " (note the appended space) as the ':' is // part of the pkgname:arch information that dpkg sends // @@ -553,8 +554,26 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) std::clog << "ignoring line: not enough ':'" << std::endl; return; } + + std::string prefix = APT::String::Strip(list[0]); + std::string pkgname; + std::string action_str; + if (prefix == "processing") + { + pkgname = APT::String::Strip(list[2]); + action_str = APT::String::Strip(list[1]); + } + else if (prefix == "status") + { + pkgname = APT::String::Strip(list[1]); + action_str = APT::String::Strip(list[2]); + } else { + if (Debug == true) + std::clog << "unknown prefix '" << prefix << "'" << std::endl; + return; + } + // dpkg does not send always send "pkgname:arch" so we add it here if needed - std::string pkgname = list[1]; if (pkgname.find(":") == std::string::npos) { // find the package in the group that is in a touched by dpkg @@ -574,13 +593,12 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) } } const char* const pkg = pkgname.c_str(); - const char* action = list[2].c_str(); - + const char* action = action_str.c_str(); std::string short_pkgname = StringSplit(pkgname, ":")[0]; // 'processing' from dpkg looks like // 'processing: action: pkg' - if(strncmp(list[0].c_str(), "processing", strlen("processing")) == 0) + if(prefix == "processing") { char s[200]; const char* const pkg_or_trigger = list[2].c_str(); @@ -609,7 +627,11 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) if (strncmp(action, "disappear", strlen("disappear")) == 0) handleDisappearAction(pkg_or_trigger); return; - } + } + + // FIXME: fix indent once the progress-refactor branch is merged + if (prefix == "status") + { if(strncmp(action,"error",strlen("error")) == 0) { @@ -670,6 +692,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) if (Debug == true) std::clog << "(parsed from dpkg) pkg: " << short_pkgname << " action: " << action << endl; + } } /*}}}*/ // DPkgPM::handleDisappearAction /*{{{*/ -- cgit v1.2.3 From 11ef54810d6241b6d2433d27099b43763dabaee3 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 18 Oct 2013 08:32:36 +0200 Subject: reshuffle dpkgpm.cc code a bit more --- apt-pkg/deb/dpkgpm.cc | 68 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 28 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index c5d40c033..41885e6e8 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -555,6 +555,8 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) return; } + // build the (prefix, pkgname, action) tuple, position of this + // is different for "processing" or "status" messages std::string prefix = APT::String::Strip(list[0]); std::string pkgname; std::string action_str; @@ -573,6 +575,38 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) return; } + // FIXME: fix indent once the progress-refactor branch is merged + if (prefix == "status") + { + + if(action_str == "error") + { + status << "pmerror:" << list[1] + << ":" << (PackagesDone/float(PackagesTotal)*100.0) + << ":" << list[3] + << endl; + if(OutStatusFd > 0) + FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); + if (Debug == true) + std::clog << "send: '" << status.str() << "'" << endl; + pkgFailures++; + WriteApportReport(list[1].c_str(), list[3].c_str()); + return; + } + else if(action_str == "conffile") + { + status << "pmconffile:" << list[1] + << ":" << (PackagesDone/float(PackagesTotal)*100.0) + << ":" << list[3] + << endl; + if(OutStatusFd > 0) + FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); + if (Debug == true) + std::clog << "send: '" << status.str() << "'" << endl; + return; + } + } + // dpkg does not send always send "pkgname:arch" so we add it here if needed if (pkgname.find(":") == std::string::npos) { @@ -595,6 +629,12 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) const char* const pkg = pkgname.c_str(); const char* action = action_str.c_str(); std::string short_pkgname = StringSplit(pkgname, ":")[0]; + std::string arch = ""; + if (pkgname.find(":") != string::npos) + arch = StringSplit(pkgname, ":")[1]; + std::string i18n_pkgname = pkgname; + if (arch.size() != 0) + strprintf(i18n_pkgname, "%s (%s)", short_pkgname.c_str(), arch.c_str()); // 'processing' from dpkg looks like // 'processing: action: pkg' @@ -629,37 +669,9 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) return; } - // FIXME: fix indent once the progress-refactor branch is merged if (prefix == "status") { - if(strncmp(action,"error",strlen("error")) == 0) - { - status << "pmerror:" << list[1] - << ":" << (PackagesDone/float(PackagesTotal)*100.0) - << ":" << list[3] - << endl; - if(OutStatusFd > 0) - FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); - if (Debug == true) - std::clog << "send: '" << status.str() << "'" << endl; - pkgFailures++; - WriteApportReport(list[1].c_str(), list[3].c_str()); - return; - } - else if(strncmp(action,"conffile",strlen("conffile")) == 0) - { - status << "pmconffile:" << list[1] - << ":" << (PackagesDone/float(PackagesTotal)*100.0) - << ":" << list[3] - << endl; - if(OutStatusFd > 0) - FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); - if (Debug == true) - std::clog << "send: '" << status.str() << "'" << endl; - return; - } - vector const &states = PackageOps[pkg]; const char *next_action = NULL; if(PackageOpsDone[pkg] < states.size()) -- cgit v1.2.3 From 27ede340880968cad79b5cc675f283480eb046f4 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 18 Oct 2013 09:28:08 +0200 Subject: reshuffle the pkgDPkgPM::ProcessDpkgStatusLine() some more to make it more robust --- apt-pkg/deb/dpkgpm.cc | 168 +++++++++++++++++++++++++++----------------------- 1 file changed, 91 insertions(+), 77 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 41885e6e8..b5d314165 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -516,29 +516,15 @@ void pkgDPkgPM::DoTerminalPty(int master) void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) { bool const Debug = _config->FindB("Debug::pkgDPkgProgressReporting",false); - // the status we output - ostringstream status; - if (Debug == true) std::clog << "got from dpkg '" << line << "'" << std::endl; - /* dpkg sends strings like this: 'status: : ' 'status: :: ' - errors look like this: - 'status: /var/cache/apt/archives/krecipes_0.8.1-0ubuntu1_i386.deb : error : trying to overwrite `/usr/share/doc/kde/HTML/en/krecipes/krectip.png', which is also in package krecipes-data - and conffile-prompt like this - 'status: conffile-prompt: conffile : 'current-conffile' 'new-conffile' useredited distedited - Newer versions of dpkg sent also: - 'processing: install: pkg' - 'processing: configure: pkg' - 'processing: remove: pkg' - 'processing: purge: pkg' - 'processing: disappear: pkg' - 'processing: trigproc: trigger' - + 'processing: {install,configure,remove,purge,disappear,trigproc}: pkg' + 'processing: {install,configure,remove,purge,disappear,trigproc}: trigger' */ // we need to split on ": " (note the appended space) as the ':' is @@ -560,11 +546,30 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) std::string prefix = APT::String::Strip(list[0]); std::string pkgname; std::string action_str; + ostringstream status; + + // "processing" has the form "processing: action: pkg or trigger" + // with action = ["install", "configure", "remove", "purge", "disappear", + // "trigproc"] if (prefix == "processing") { pkgname = APT::String::Strip(list[2]); action_str = APT::String::Strip(list[1]); + + // this is what we support in the processing stage + if(action_str != "install" && action_str != "configure" && + action_str != "remove" && action_str != "purge" && + action_str != "purge") + { + if (Debug == true) + std::clog << "ignoring processing action: '" << action_str + << "'" << std::endl; + return; + } } + // "status" has the form: "status: pkg: state" + // with state in ["half-installed", "unpacked", "half-configured", + // "installed", "config-files", "not-installed"] else if (prefix == "status") { pkgname = APT::String::Strip(list[1]); @@ -575,38 +580,47 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) return; } - // FIXME: fix indent once the progress-refactor branch is merged - if (prefix == "status") - { - if(action_str == "error") - { - status << "pmerror:" << list[1] - << ":" << (PackagesDone/float(PackagesTotal)*100.0) - << ":" << list[3] - << endl; - if(OutStatusFd > 0) - FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); - if (Debug == true) - std::clog << "send: '" << status.str() << "'" << endl; - pkgFailures++; - WriteApportReport(list[1].c_str(), list[3].c_str()); - return; - } - else if(action_str == "conffile") + /* handle the special cases first: + + errors look like this: + 'status: /var/cache/apt/archives/krecipes_0.8.1-0ubuntu1_i386.deb : error : trying to overwrite `/usr/share/doc/kde/HTML/en/krecipes/krectip.png', which is also in package krecipes-data + and conffile-prompt like this + 'status: conffile-prompt: conffile : 'current-conffile' 'new-conffile' useredited distedited + */ + if (prefix == "status") { - status << "pmconffile:" << list[1] - << ":" << (PackagesDone/float(PackagesTotal)*100.0) - << ":" << list[3] - << endl; - if(OutStatusFd > 0) - FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); - if (Debug == true) - std::clog << "send: '" << status.str() << "'" << endl; - return; - } + if(action_str == "error") + { + status << "pmerror:" << list[1] + << ":" << (PackagesDone/float(PackagesTotal)*100.0) + << ":" << list[3] + << endl; + if(OutStatusFd > 0) + FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); + if (Debug == true) + std::clog << "send: '" << status.str() << "'" << endl; + pkgFailures++; + WriteApportReport(list[1].c_str(), list[3].c_str()); + return; + } + else if(action_str == "conffile") + { + status << "pmconffile:" << list[1] + << ":" << (PackagesDone/float(PackagesTotal)*100.0) + << ":" << list[3] + << endl; + if(OutStatusFd > 0) + FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); + if (Debug == true) + std::clog << "send: '" << status.str() << "'" << endl; + return; + } } + // at this point we know that we should have a valid pkgname, so build all + // the info from it + // dpkg does not send always send "pkgname:arch" so we add it here if needed if (pkgname.find(":") == std::string::npos) { @@ -626,6 +640,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) } } } + const char* const pkg = pkgname.c_str(); const char* action = action_str.c_str(); std::string short_pkgname = StringSplit(pkgname, ":")[0]; @@ -671,39 +686,38 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) if (prefix == "status") { - - vector const &states = PackageOps[pkg]; - const char *next_action = NULL; - if(PackageOpsDone[pkg] < states.size()) - next_action = states[PackageOpsDone[pkg]].state; - // check if the package moved to the next dpkg state - if(next_action && (strcmp(action, next_action) == 0)) - { - // only read the translation if there is actually a next - // action - const char *translation = _(states[PackageOpsDone[pkg]].str); - char s[200]; - snprintf(s, sizeof(s), translation, short_pkgname.c_str()); - - // we moved from one dpkg state to a new one, report that - PackageOpsDone[pkg]++; - PackagesDone++; - // build the status str - status << "pmstatus:" << short_pkgname - << ":" << (PackagesDone/float(PackagesTotal)*100.0) - << ":" << s - << endl; - if(_config->FindB("DPkgPM::Progress", false) == true) - SendTerminalProgress(PackagesDone/float(PackagesTotal)*100.0); - - if(OutStatusFd > 0) - FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); - if (Debug == true) - std::clog << "send: '" << status.str() << "'" << endl; - } - if (Debug == true) - std::clog << "(parsed from dpkg) pkg: " << short_pkgname - << " action: " << action << endl; + vector const &states = PackageOps[pkg]; + const char *next_action = NULL; + if(PackageOpsDone[pkg] < states.size()) + next_action = states[PackageOpsDone[pkg]].state; + // check if the package moved to the next dpkg state + if(next_action && (strcmp(action, next_action) == 0)) + { + // only read the translation if there is actually a next + // action + const char *translation = _(states[PackageOpsDone[pkg]].str); + char s[200]; + snprintf(s, sizeof(s), translation, short_pkgname.c_str()); + + // we moved from one dpkg state to a new one, report that + PackageOpsDone[pkg]++; + PackagesDone++; + // build the status str + status << "pmstatus:" << short_pkgname + << ":" << (PackagesDone/float(PackagesTotal)*100.0) + << ":" << s + << endl; + if(_config->FindB("DPkgPM::Progress", false) == true) + SendTerminalProgress(PackagesDone/float(PackagesTotal)*100.0); + + if(OutStatusFd > 0) + FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); + if (Debug == true) + std::clog << "send: '" << status.str() << "'" << endl; + } + if (Debug == true) + std::clog << "(parsed from dpkg) pkg: " << short_pkgname + << " action: " << action << endl; } } /*}}}*/ -- cgit v1.2.3 From fa300ed15fc5a1d9e146c85d45f0a88b1d7f96bf Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 18 Oct 2013 09:40:05 +0200 Subject: use std::string instead of char* in pkgDPkgPM::ProcessDpkgStatusLine() --- apt-pkg/deb/dpkgpm.cc | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index b5d314165..0ebd9f28b 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -545,7 +545,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) // is different for "processing" or "status" messages std::string prefix = APT::String::Strip(list[0]); std::string pkgname; - std::string action_str; + std::string action; ostringstream status; // "processing" has the form "processing: action: pkg or trigger" @@ -554,15 +554,14 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) if (prefix == "processing") { pkgname = APT::String::Strip(list[2]); - action_str = APT::String::Strip(list[1]); + action = APT::String::Strip(list[1]); // this is what we support in the processing stage - if(action_str != "install" && action_str != "configure" && - action_str != "remove" && action_str != "purge" && - action_str != "purge") + if(action != "install" && action != "configure" && + action != "remove" && action != "purge" && action != "purge") { if (Debug == true) - std::clog << "ignoring processing action: '" << action_str + std::clog << "ignoring processing action: '" << action << "'" << std::endl; return; } @@ -573,7 +572,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) else if (prefix == "status") { pkgname = APT::String::Strip(list[1]); - action_str = APT::String::Strip(list[2]); + action = APT::String::Strip(list[2]); } else { if (Debug == true) std::clog << "unknown prefix '" << prefix << "'" << std::endl; @@ -590,7 +589,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) */ if (prefix == "status") { - if(action_str == "error") + if(action == "error") { status << "pmerror:" << list[1] << ":" << (PackagesDone/float(PackagesTotal)*100.0) @@ -604,7 +603,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) WriteApportReport(list[1].c_str(), list[3].c_str()); return; } - else if(action_str == "conffile") + else if(action == "conffile") { status << "pmconffile:" << list[1] << ":" << (PackagesDone/float(PackagesTotal)*100.0) @@ -621,7 +620,8 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) // at this point we know that we should have a valid pkgname, so build all // the info from it - // dpkg does not send always send "pkgname:arch" so we add it here if needed + // dpkg does not send always send "pkgname:arch" so we add it here + // if needed if (pkgname.find(":") == std::string::npos) { // find the package in the group that is in a touched by dpkg @@ -642,7 +642,6 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) } const char* const pkg = pkgname.c_str(); - const char* action = action_str.c_str(); std::string short_pkgname = StringSplit(pkgname, ":")[0]; std::string arch = ""; if (pkgname.find(":") != string::npos) @@ -655,32 +654,33 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) // 'processing: action: pkg' if(prefix == "processing") { - char s[200]; - const char* const pkg_or_trigger = list[2].c_str(); - action = list[1].c_str(); const std::pair * const iter = std::find_if(PackageProcessingOpsBegin, PackageProcessingOpsEnd, - MatchProcessingOp(action)); + MatchProcessingOp(action.c_str())); if(iter == PackageProcessingOpsEnd) { if (Debug == true) std::clog << "ignoring unknown action: " << action << std::endl; return; } - snprintf(s, sizeof(s), _(iter->second), pkg_or_trigger); + std::string msg; + strprintf(msg, _(iter->second), short_pkgname.c_str()); - status << "pmstatus:" << pkg_or_trigger + status << "pmstatus:" << short_pkgname << ":" << (PackagesDone/float(PackagesTotal)*100.0) - << ":" << s + << ":" << msg << endl; if(OutStatusFd > 0) FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); if (Debug == true) std::clog << "send: '" << status.str() << "'" << endl; - if (strncmp(action, "disappear", strlen("disappear")) == 0) - handleDisappearAction(pkg_or_trigger); + // FIXME: this needs a muliarch testcase + // FIXME2: is "pkgname" here reliable with dpkg only sending us + // short pkgnames? + if (action == "disappear") + handleDisappearAction(pkgname); return; } @@ -691,13 +691,13 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) if(PackageOpsDone[pkg] < states.size()) next_action = states[PackageOpsDone[pkg]].state; // check if the package moved to the next dpkg state - if(next_action && (strcmp(action, next_action) == 0)) + if(next_action && (action == next_action)) { // only read the translation if there is actually a next // action const char *translation = _(states[PackageOpsDone[pkg]].str); - char s[200]; - snprintf(s, sizeof(s), translation, short_pkgname.c_str()); + std::string msg; + strprintf(msg, translation, short_pkgname.c_str()); // we moved from one dpkg state to a new one, report that PackageOpsDone[pkg]++; @@ -705,7 +705,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) // build the status str status << "pmstatus:" << short_pkgname << ":" << (PackagesDone/float(PackagesTotal)*100.0) - << ":" << s + << ":" << msg << endl; if(_config->FindB("DPkgPM::Progress", false) == true) SendTerminalProgress(PackagesDone/float(PackagesTotal)*100.0); -- cgit v1.2.3