From 99055353a54094034c8a526aa336cd59a039676c Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 17 Jun 2014 13:47:01 +0200 Subject: don't send pkg from an unknown architecture via EDSP APT's cache can include packages from architectures dpkg has no knowledge about and can therefore not be installed for e.g. to allow easy lookups. There is no point in telling external solvers about them though and some of them might even be really talkative about ignoring them if we do. --- apt-pkg/edsp.cc | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'apt-pkg') diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index 6d1b68c23..0d0418e06 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -50,7 +51,12 @@ bool EDSP::WriteScenario(pkgDepCache &Cache, FILE* output, OpProgress *Progress) if (Progress != NULL) Progress->SubProgress(Cache.Head().VersionCount, _("Send scenario to solver")); unsigned long p = 0; + std::vector archs = APT::Configuration::getArchitectures(); for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg) + { + std::string const arch = Pkg.Arch(); + if (std::find(archs.begin(), archs.end(), arch) == archs.end()) + continue; for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver, ++p) { WriteScenarioVersion(Cache, output, Pkg, Ver); @@ -59,6 +65,7 @@ bool EDSP::WriteScenario(pkgDepCache &Cache, FILE* output, OpProgress *Progress) if (Progress != NULL && p % 100 == 0) Progress->Progress(p); } + } return true; } /*}}}*/ -- cgit v1.2.3 From 224dc038412459a5f64d4e7a16845847b7797a67 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 17 Jun 2014 16:55:19 +0200 Subject: fix SubstVar to be usable as a replace_all method The name suggests that it is supposed to substitute a variable with a value, but we tend to use it in a more liberal replace_all() fashion, but this breaks if either of the parameters is empty or more importantly if two "variable" occurrences follow each other directly. --- apt-pkg/contrib/strutl.cc | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index 2100ee47b..ce69c7a02 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -434,23 +434,30 @@ string TimeToStr(unsigned long Sec) /* This replaces all occurrences of Subst with Contents in Str. */ string SubstVar(const string &Str,const string &Subst,const string &Contents) { + if (Subst.empty() == true) + return Str; + string::size_type Pos = 0; string::size_type OldPos = 0; string Temp; - - while (OldPos < Str.length() && + + while (OldPos < Str.length() && (Pos = Str.find(Subst,OldPos)) != string::npos) { - Temp += string(Str,OldPos,Pos) + Contents; - OldPos = Pos + Subst.length(); + if (OldPos != Pos) + Temp.append(Str, OldPos, Pos - OldPos); + if (Contents.empty() == false) + Temp.append(Contents); + OldPos = Pos + Subst.length(); } - + if (OldPos == 0) return Str; - + + if (OldPos >= Str.length()) + return Temp; return Temp + string(Str,OldPos); } - string SubstVar(string Str,const struct SubstVar *Vars) { for (; Vars->Subst != 0; Vars++) -- cgit v1.2.3 From 172947cd7dc5c88c94c6ad269dc6c6be002ee958 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 17 Jun 2014 19:05:53 +0200 Subject: do not call resolver twice on (dist-)upgrade --- apt-pkg/upgrade.cc | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'apt-pkg') diff --git a/apt-pkg/upgrade.cc b/apt-pkg/upgrade.cc index 7926845c2..29b11937b 100644 --- a/apt-pkg/upgrade.cc +++ b/apt-pkg/upgrade.cc @@ -143,6 +143,12 @@ static bool pkgAllUpgradeNoNewPackages(pkgDepCache &Cache) */ static bool pkgAllUpgradeWithNewPackages(pkgDepCache &Cache) { + std::string const solver = _config->Find("APT::Solver", "internal"); + if (solver != "internal") { + OpTextProgress Prog(*_config); + return EDSP::ResolveExternal(solver.c_str(), Cache, true, false, false, &Prog); + } + pkgDepCache::ActionGroup group(Cache); pkgProblemResolver Fix(&Cache); -- cgit v1.2.3 From 19818b65467e954a55e2af56111233ce305d5508 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 3 Jul 2014 18:20:44 +0200 Subject: Try not to parse invalid translation files (LP: #756317) --- apt-pkg/acquire-item.cc | 42 +++++++++++++++++------------------------- apt-pkg/acquire-item.h | 11 ++--------- 2 files changed, 19 insertions(+), 34 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 0178456a8..0911d11b7 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -932,8 +932,6 @@ pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner, } CompressionExtension = comprExt; - Verify = true; - Init(URI, URIDesc, ShortDesc); } pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner, IndexTarget const *Target, @@ -957,13 +955,6 @@ pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner, IndexTarget const *Target, if (CompressionExtension.empty() == false) CompressionExtension.erase(CompressionExtension.end()-1); - // only verify non-optional targets, see acquire-item.h for a FIXME - // to make this more flexible - if (Target->IsOptional()) - Verify = false; - else - Verify = true; - Init(Target->URI, Target->Description, Target->ShortDesc); } /*}}}*/ @@ -1056,23 +1047,24 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,string Hash, return; } - /* Verify the index file for correctness (all indexes must - * have a Package field) (LP: #346386) (Closes: #627642) */ - if (Verify == true) + // FIXME: this can go away once we only ever download stuff that + // has a valid hash and we never do GET based probing + // + /* Always verify the index file for correctness (all indexes must + * have a Package field) (LP: #346386) (Closes: #627642) + */ + FileFd fd(DestFile, FileFd::ReadOnly); + // Only test for correctness if the file is not empty (empty is ok) + if (fd.FileSize() > 0) { - FileFd fd(DestFile, FileFd::ReadOnly); - // 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; - } + 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; } } diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index f48d2a0d7..06537bf2c 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -685,15 +685,8 @@ class pkgAcqIndex : public pkgAcquire::Item */ bool Erase; - /** \brief Verify for correctness by checking if a "Package" - * tag is found in the index. This can be set to - * false for optional index targets - * - */ - // FIXME: instead of a bool it should use a verify string that will - // then be used in the pkgAcqIndex::Done method to ensure that - // the downloaded file contains the expected tag - bool Verify; + // Unused, used to be used to verify that "Packages: " header was there + bool __DELME_ON_NEXT_ABI_BREAK_Verify; /** \brief The download request that is currently being * processed. -- cgit v1.2.3 From 4ea471ecb013d188d03a5c3efb9b21e58ef56065 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 7 Jul 2014 17:19:29 +0200 Subject: handle moved mmap after UniqFindTagWrite call A call to UniqFindTagWrite can trigger the need for a bigger mmap, which is usually done by moving it, but with this move all pointers into it become invalid (and have to be remapped). The compiler calculates the pointer before the execution of the call though, so it tries to store the returned value at the old location, resulting in a segfault. We solve this by use of a temprorary variable as we did in the other instances of this problem before. Closes: #753941 --- apt-pkg/deb/deblistparser.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index a1bcfb710..02b9cb239 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -145,7 +145,8 @@ unsigned char debListParser::ParseMultiArch(bool const showErrors) /*{{{*/ bool debListParser::NewVersion(pkgCache::VerIterator &Ver) { // Parse the section - Ver->Section = UniqFindTagWrite("Section"); + unsigned long const idxSection = UniqFindTagWrite("Section"); + Ver->Section = idxSection; Ver->MultiArch = ParseMultiArch(true); // Archive Size Ver->Size = Section.FindULL("Size"); @@ -260,7 +261,10 @@ bool debListParser::UsePackage(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver) { if (Pkg->Section == 0) - Pkg->Section = UniqFindTagWrite("Section"); + { + unsigned long const idxSection = UniqFindTagWrite("Section"); + Pkg->Section = idxSection; + } string const static myArch = _config->Find("APT::Architecture"); // Possible values are: "all", "native", "installed" and "none" -- cgit v1.2.3 From 10ecfe4f8a617ab285abd99d67917ae332ed2e4a Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 8 Jul 2014 11:27:01 +0200 Subject: Do not clean "/" in pkgAcquire::Clean/pkgArchiveCleaner Having "/" here is most likely a user configuration error and may cause removal of import symlinks like /vmlinuz Closes: #753531 --- apt-pkg/acquire.cc | 3 +++ apt-pkg/clean.cc | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc index a187a00ae..057bc24cd 100644 --- a/apt-pkg/acquire.cc +++ b/apt-pkg/acquire.cc @@ -486,6 +486,9 @@ bool pkgAcquire::Clean(string Dir) if (DirectoryExists(Dir) == false) return true; + if(Dir == "/") + return _error->Error(_("Clean of %s is not supported"), Dir.c_str()); + DIR *D = opendir(Dir.c_str()); if (D == 0) return _error->Errno("opendir",_("Unable to read %s"),Dir.c_str()); diff --git a/apt-pkg/clean.cc b/apt-pkg/clean.cc index 0ee3b765d..37128e9aa 100644 --- a/apt-pkg/clean.cc +++ b/apt-pkg/clean.cc @@ -34,7 +34,10 @@ bool pkgArchiveCleaner::Go(std::string Dir,pkgCache &Cache) { bool CleanInstalled = _config->FindB("APT::Clean-Installed",true); - + + if(Dir == "/") + return _error->Error(_("Clean of %s is not supported"), Dir.c_str()); + DIR *D = opendir(Dir.c_str()); if (D == 0) return _error->Errno("opendir",_("Unable to read %s"),Dir.c_str()); -- cgit v1.2.3 From 08be0ca32ad69e9ebf28fe26aa85990700c81cf6 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Wed, 16 Jul 2014 13:57:50 +0200 Subject: StringToBool: only act if the entire string is consumed by strtol() StringToBool uses strtol() internally to check if the argument is a number. This function stops when it does not find any more numbers. So a string like "0ad" (which is a valid packagename) is interpreted as a "0". The code now checks that the entire string is consumed not just a part of it. Thanks to Johannes Schauer for raising this issue. --- apt-pkg/contrib/strutl.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index ce69c7a02..922229e90 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -704,9 +704,12 @@ string LookupTag(const string &Message,const char *Tag,const char *Default) then returns the result. Several varients on true/false are checked. */ int StringToBool(const string &Text,int Default) { - char *End; - int Res = strtol(Text.c_str(),&End,0); - if (End != Text.c_str() && Res >= 0 && Res <= 1) + char *ParseEnd; + int Res = strtol(Text.c_str(),&ParseEnd,0); + // ensure that the entire string was converted by strtol to avoid + // failures on "apt-cache show -a 0ad" where the "0" is converted + const char *TextEnd = Text.c_str()+Text.size(); + if (ParseEnd == TextEnd && Res >= 0 && Res <= 1) return Res; // Check for positives -- cgit v1.2.3 From 31b9d84143f7330f4ad60eaa2c8877d28e00cffa Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 17 Jul 2014 09:59:55 +0200 Subject: apt-pkg/acquire-item.cc: make pkgAcqDiffIndex more uniform --- apt-pkg/acquire-item.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 0911d11b7..6cb9b012a 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -356,7 +356,7 @@ pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner, Desc.URI = URI + ".diff/Index"; DestFile = _config->FindDir("Dir::State::lists") + "partial/"; - DestFile += URItoFileName(URI) + string(".DiffIndex"); + DestFile += URItoFileName(Desc.URI); if(Debug) std::clog << "pkgAcqDiffIndex: " << Desc.URI << std::endl; @@ -392,7 +392,7 @@ pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner, string pkgAcqDiffIndex::Custom600Headers() { string Final = _config->FindDir("Dir::State::lists"); - Final += URItoFileName(RealURI) + string(".IndexDiff"); + Final += URItoFileName(Desc.URI); if(Debug) std::clog << "Custom600Header-IMS: " << Final << std::endl; -- cgit v1.2.3 From 2f58969150b0daec1de407f61385ccf5b2065aa3 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 29 Jul 2014 15:01:13 +0200 Subject: Fix SmartConfigure to ignore ordering of packages that are already valid With the change of SmartConfigure() in git commit 42d51f the ordering code was trying to re-order dependencies, even when at this point in time this was not needed. Now it will first check all targets of the given dependency and only if there is not a good one try to reorder and unpack/configure as needed. Closes: LP: #1347721 --- apt-pkg/packagemanager.cc | 49 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc index 393f836f7..249542c68 100644 --- a/apt-pkg/packagemanager.cc +++ b/apt-pkg/packagemanager.cc @@ -372,6 +372,8 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) std::list needConfigure; do { + // Check each dependency and see if anything needs to be done + // so that it can be configured Changed = false; for (DepIterator D = instVer.DependsList(); D.end() == false; ) { @@ -383,7 +385,8 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) continue; Bad = true; - // Check for dependencies that have not been unpacked, probably due to loops. + // the first pass checks if we its all good, i.e. if we have + // to do anything at all for (DepIterator Cur = Start; true; ++Cur) { SPtrArray VList = Cur.AllTargets(); @@ -402,6 +405,47 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) break; } + // Check if the version that is going to be installed will satisfy the dependency + if (Cache[DepPkg].InstallVer != *I || List->IsNow(DepPkg) == false) + continue; + + if (PkgLoop == true) + { + if (Debug) + std::clog << OutputInDepth(Depth) << "Package " << Pkg << " loops in SmartConfigure" << std::endl; + Bad = false; + } + } + + if (Cur == End || Bad == false) + break; + } + + // this dependency is in a good state, so we can stop + if (Bad == false) + { + if (Debug) + std::clog << OutputInDepth(Depth) << "Found ok dep " << D.TargetPkg() << std::endl; + continue; + } + + // Check for dependencies that have not been unpacked, + // probably due to loops. + for (DepIterator Cur = Start; true; ++Cur) + { + SPtrArray VList = Cur.AllTargets(); + + for (Version **I = VList; *I != 0; ++I) + { + VerIterator Ver(Cache,*I); + PkgIterator DepPkg = Ver.ParentPkg(); + + // Check if the current version of the package is available and will satisfy this dependency + if (DepPkg.CurrentVer() == Ver && List->IsNow(DepPkg) == true && + List->IsFlag(DepPkg,pkgOrderList::Removed) == false && + DepPkg.State() == PkgIterator::NeedsNothing) + continue; + // Check if the version that is going to be installed will satisfy the dependency if (Cache[DepPkg].InstallVer != *I || List->IsNow(DepPkg) == false) continue; @@ -419,6 +463,8 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) if (NonLoopingSmart(UNPACK_IMMEDIATE, Pkg, DepPkg, Depth, PkgLoop, &Bad, &Changed) == false) return false; } + // at this point we either unpacked a Dep or we are in a loop, + // no need to unpack a second one break; } @@ -435,6 +481,7 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) return _error->Error("Internal error: MaxLoopCount reached in SmartUnPack (1) for %s, aborting", Pkg.FullName().c_str()); } while (Changed == true); + // now go over anything that needs configuring Bad = false, Changed = false, i = 0; do { -- cgit v1.2.3 From 8f617600aeb931574baf0b53617e7759baa3f370 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Sun, 24 Aug 2014 18:43:07 +0200 Subject: Fix debListParser to accept "no" as a value for the Multi-Arch field Seems this was missed somehow. Closes: #759099 --- apt-pkg/deb/deblistparser.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 02b9cb239..28c898542 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -108,7 +108,7 @@ unsigned char debListParser::ParseMultiArch(bool const showErrors) /*{{{*/ { unsigned char MA; string const MultiArch = Section.FindS("Multi-Arch"); - if (MultiArch.empty() == true) + if (MultiArch.empty() == true || MultiArch == "no") MA = pkgCache::Version::None; else if (MultiArch == "same") { if (ArchitectureAll() == true) -- cgit v1.2.3 From 40faab46c4d5fa766c80090f0fdb54120dbb37f2 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 16 Aug 2014 16:33:46 +0200 Subject: support versioned provides as implemented by dpkg APT supported versioned provides for a long while in an attempt to get it working with rpm. While this support is old, we can be relatively sure that it works as versioned provides are used internally to make Multi-Arch:foreign work. Previous versions of apt will print a warning indicating that the versioned provides is ignored, so that something which "Provides: foo (= 2)" doesn't provide anything. Note that dpkg does allow only a equals-relation in the provides line as anything else is deemed too complex. apt doesn't support anything else either and such a support would require potentially big changes. Closes: 758153 --- apt-pkg/deb/deblistparser.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 28c898542..7d4fd52cf 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -803,8 +803,8 @@ bool debListParser::ParseProvides(pkgCache::VerIterator &Ver) Start = ParseDepends(Start,Stop,Package,Version,Op); if (Start == 0) return _error->Error("Problem parsing Provides line"); - if (Op != pkgCache::Dep::NoOp) { - _error->Warning("Ignoring Provides line with DepCompareOp for package %s", Package.c_str()); + if (Op != pkgCache::Dep::NoOp && Op != pkgCache::Dep::Equals) { + _error->Warning("Ignoring Provides line with non-equal DepCompareOp for package %s", Package.c_str()); } else if ((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign) { if (NewProvidesAllArch(Ver, Package, Version) == false) return false; -- cgit v1.2.3 From fb4c76436a88a04d1d9b7e9622e431ed8ab708a6 Mon Sep 17 00:00:00 2001 From: Warren He Date: Fri, 29 Aug 2014 11:15:30 +0200 Subject: initialize iPolicyBrokenCount in DepCache::Update All other counters are correctly initialized here, expect this one. The practical effect is low as in apt we usually just do "!= 0" checks, but only correct counters are good counters. Closes: 758397 --- apt-pkg/depcache.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index c25672d1c..42e31396b 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -663,10 +663,11 @@ void pkgDepCache::Update(OpProgress *Prog) { iUsrSize = 0; iDownloadSize = 0; - iDelCount = 0; iInstCount = 0; + iDelCount = 0; iKeepCount = 0; iBrokenCount = 0; + iPolicyBrokenCount = 0; iBadCount = 0; // Perform the depends pass -- cgit v1.2.3 From c6ee61eab54edf6cc3fbe118d304d72a860e1451 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 2 Sep 2014 15:50:19 +0200 Subject: Make Proxy-Auto-Detect check for each host When doing Acquire::http{,s}::Proxy-Auto-Detect, run the auto-detect command for each host instead of only once. This should make using "proxy" from libproxy-tools feasible which can then be used for PAC style or other proxy configurations. Closes: #759264 --- apt-pkg/contrib/proxy.cc | 82 ++++++++++++++++++++++++++++++++++++++++++++++++ apt-pkg/contrib/proxy.h | 16 ++++++++++ 2 files changed, 98 insertions(+) create mode 100644 apt-pkg/contrib/proxy.cc create mode 100644 apt-pkg/contrib/proxy.h (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/proxy.cc b/apt-pkg/contrib/proxy.cc new file mode 100644 index 000000000..b58db8478 --- /dev/null +++ b/apt-pkg/contrib/proxy.cc @@ -0,0 +1,82 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/* ###################################################################### + + Proxy - Proxy releated functions + + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#include +#include +#include +#include + +#include +#include + +#include "proxy.h" + + +// AutoDetectProxy - auto detect proxy /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool AutoDetectProxy(URI &URL) +{ + // we support both http/https debug options + bool Debug = _config->FindB("Debug::Acquire::"+URL.Access,false); + + // option is "Acquire::http::Proxy-Auto-Detect" but we allow the old + // name without the dash ("-") + std::string AutoDetectProxyCmd = _config->Find("Acquire::"+URL.Access+"::Proxy-Auto-Detect", + _config->Find("Acquire::"+URL.Access+"::ProxyAutoDetect")); + + if (AutoDetectProxyCmd.empty()) + return true; + + if (Debug) + std::clog << "Using auto proxy detect command: " << AutoDetectProxyCmd << std::endl; + + int Pipes[2] = {-1,-1}; + if (pipe(Pipes) != 0) + return _error->Errno("pipe", "Failed to create Pipe"); + + pid_t Process = ExecFork(); + if (Process == 0) + { + close(Pipes[0]); + dup2(Pipes[1],STDOUT_FILENO); + SetCloseExec(STDOUT_FILENO,false); + + std::string foo = URL; + const char *Args[4]; + Args[0] = AutoDetectProxyCmd.c_str(); + Args[1] = foo.c_str(); + Args[2] = 0; + execv(Args[0],(char **)Args); + std::cerr << "Failed to exec method " << Args[0] << std::endl; + _exit(100); + } + char buf[512]; + int InFd = Pipes[0]; + close(Pipes[1]); + int res = read(InFd, buf, sizeof(buf)-1); + ExecWait(Process, "ProxyAutoDetect", true); + + if (res < 0) + return _error->Errno("read", "Failed to read"); + if (res == 0) + return _error->Warning("ProxyAutoDetect returned no data"); + + // add trailing \0 + buf[res] = 0; + + if (Debug) + std::clog << "auto detect command returned: '" << buf << "'" << std::endl; + + if (strstr(buf, URL.Access.c_str()) == buf) + _config->Set("Acquire::"+URL.Access+"::proxy::"+URL.Host, _strstrip(buf)); + + return true; +} + /*}}}*/ diff --git a/apt-pkg/contrib/proxy.h b/apt-pkg/contrib/proxy.h new file mode 100644 index 000000000..2cbcd07b4 --- /dev/null +++ b/apt-pkg/contrib/proxy.h @@ -0,0 +1,16 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/* ###################################################################### + + Proxy - Proxy operations + + ##################################################################### */ + /*}}}*/ +#ifndef PKGLIB_PROXY_H +#define PKGLIB_PROXY_H + +class URI; +bool AutoDetectProxy(URI &URL); + + +#endif -- cgit v1.2.3 From cbcdd3ee9d86379d1b3a44e41ae8b17dc23111d0 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 2 Sep 2014 17:24:24 +0200 Subject: * apt-pkg/deb/dpkgpm.cc: - update string matching for dpkg I/O errors. (LP: #1363257) - properly parse the dpkg status line so that package name is properly set and an apport report is created. Thanks to Anders Kaseorg for the patch. (LP: #1353171) --- apt-pkg/deb/dpkgpm.cc | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 613a4de9f..264304c61 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -621,15 +621,15 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) { if(action == "error") { - d->progress->Error(list[1], PackagesDone, PackagesTotal, + d->progress->Error(pkgname, PackagesDone, PackagesTotal, list[3]); pkgFailures++; - WriteApportReport(list[1].c_str(), list[3].c_str()); + WriteApportReport(pkgname.c_str(), list[3].c_str()); return; } else if(action == "conffile-prompt") { - d->progress->ConffilePrompt(list[1], PackagesDone, PackagesTotal, + d->progress->ConffilePrompt(pkgname, PackagesDone, PackagesTotal, list[3]); return; } @@ -1668,9 +1668,10 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg) // do not report dpkg I/O errors, this is a format string, so we compare // the prefix and the suffix of the error with the dpkg error message vector io_errors; - io_errors.push_back(string("failed to read on buffer copy for %s")); - io_errors.push_back(string("failed in write on buffer copy for %s")); - io_errors.push_back(string("short read on buffer copy for %s")); + io_errors.push_back(string("failed to read")); + io_errors.push_back(string("failed to write")); + io_errors.push_back(string("failed to seek")); + io_errors.push_back(string("unexpected end of file or stream")); for (vector::iterator I = io_errors.begin(); I != io_errors.end(); ++I) { -- cgit v1.2.3 From 592d06b6f3c2ef2ae47c38005ae3c4e96a0841f2 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 5 Sep 2014 12:50:15 +0200 Subject: Ensure we have a Policy in CacheFile.BuildDepCache() This partly reverts d059cc2 and fixes bug #753297 in a more general way by ensuring that CacheFile.BuildDepCache() builds a pkgPolicy if there isn't one already. --- apt-pkg/cachefile.cc | 3 +++ 1 file changed, 3 insertions(+) (limited to 'apt-pkg') diff --git a/apt-pkg/cachefile.cc b/apt-pkg/cachefile.cc index 0fd40106f..ea3d45480 100644 --- a/apt-pkg/cachefile.cc +++ b/apt-pkg/cachefile.cc @@ -143,6 +143,9 @@ bool pkgCacheFile::BuildDepCache(OpProgress *Progress) if (DCache != NULL) return true; + if (BuildPolicy(Progress) == false) + return false; + DCache = new pkgDepCache(Cache,Policy); if (_error->PendingError() == true) return false; -- cgit v1.2.3 From 25594bb5bddc031afc4d62f3164cd9116d778517 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 2 Sep 2014 18:20:49 +0200 Subject: make GetLocalitySortedVersionSet more generic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No reason in and of by itself at the moment, but prepares for the goal of having 'apt search' and 'apt-cache search' using the same code now that they at least support the same stuff. The 'apt' code is just a multitude slower at the moment… Git-Dch: Ignore --- apt-pkg/cachefilter.h | 1 + 1 file changed, 1 insertion(+) (limited to 'apt-pkg') diff --git a/apt-pkg/cachefilter.h b/apt-pkg/cachefilter.h index 49d2855f5..6d10d1163 100644 --- a/apt-pkg/cachefilter.h +++ b/apt-pkg/cachefilter.h @@ -73,6 +73,7 @@ public: bool operator() (pkgCache::VerIterator const &Ver); ~PackageArchitectureMatchesSpecification(); }; + /*}}}*/ #else -- cgit v1.2.3 From b578738870e83db4e61d6f6591bc73884108b7d4 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 7 Sep 2014 21:27:57 +0200 Subject: strip everything spacey in APT::String::Strip Git-Dch: Ignore --- apt-pkg/contrib/strutl.cc | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index 922229e90..87f57a30e 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -45,14 +45,26 @@ using namespace std; // --------------------------------------------------------------------- namespace APT { namespace String { -std::string Strip(const std::string &s) +std::string Strip(const std::string &str) { - size_t start = s.find_first_not_of(" \t\n"); - // only whitespace - if (start == string::npos) + // ensure we have at least one character + if (str.empty() == true) + return str; + + char const * const s = str.c_str(); + size_t start = 0; + for (; isspace(s[start]) != 0; ++start) + ; // find the first not-space + + // string contains only whitespaces + if (s[start] == '\0') return ""; - size_t end = s.find_last_not_of(" \t\n"); - return s.substr(start, end-start+1); + + size_t end = str.length() - 1; + for (; isspace(s[end]) != 0; --end) + ; // find the last not-space + + return str.substr(start, end - start + 1); } bool Endswith(const std::string &s, const std::string &end) -- cgit v1.2.3 From 4c559e97ba4cc0d3a2995b7c451e606539d2f1be Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 8 Sep 2014 17:14:17 +0200 Subject: fix progress report for upgrade and reinstall APT treats upgrades like installs and dpkg is very similar in this, but prints still a slightly different processing message indicating that it is really an upgrade which we hadn't parsed so far, but this wasn't really visible as we quickly moved on to a 'known' state. More problematic was the reinstall case as apt hadn't recognized this for the package name detection, so that reinstalls had no progress since we introduced MultiArch. --- apt-pkg/deb/dpkgpm.cc | 79 ++++++++++++++++++++++++++------------------------- 1 file changed, 41 insertions(+), 38 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 264304c61..5411d9ee8 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -564,8 +564,8 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) 'status: : ' 'status: :: ' - 'processing: {install,configure,remove,purge,disappear,trigproc}: pkg' - 'processing: {install,configure,remove,purge,disappear,trigproc}: trigger' + 'processing: {install,upgrade,configure,remove,purge,disappear,trigproc}: pkg' + 'processing: {install,upgrade,configure,remove,purge,disappear,trigproc}: trigger' */ // we need to split on ": " (note the appended space) as the ':' is @@ -589,12 +589,15 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) std::string action; // "processing" has the form "processing: action: pkg or trigger" - // with action = ["install", "configure", "remove", "purge", "disappear", - // "trigproc"] + // with action = ["install", "upgrade", "configure", "remove", "purge", + // "disappear", "trigproc"] if (prefix == "processing") { pkgname = APT::String::Strip(list[2]); action = APT::String::Strip(list[1]); + // we don't care for the difference (as dpkg doesn't really either) + if (action == "upgrade") + action = "install"; } // "status" has the form: "status: pkg: state" // with state in ["half-installed", "unpacked", "half-configured", @@ -638,27 +641,26 @@ void pkgDPkgPM::ProcessDpkgStatusLine(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 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 - // if there are multiple dpkg will send us a full pkgname:arch + // find the package in the group that is touched by dpkg + // if there are multiple pkgs dpkg would send us a full pkgname:arch pkgCache::GrpIterator Grp = Cache.FindGrp(pkgname); - if (Grp.end() == false) + 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; - } - } + pkgCache::PkgIterator P = Grp.PackageList(); + for (; P.end() != true; P = Grp.NextPkg(P)) + { + if(Cache[P].Keep() == false || Cache[P].ReInstall() == true) + { + pkgname = P.FullName(); + break; + } + } } } - + const char* const pkg = pkgname.c_str(); std::string short_pkgname = StringSplit(pkgname, ":")[0]; std::string arch = ""; @@ -697,28 +699,29 @@ void pkgDPkgPM::ProcessDpkgStatusLine(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 && (action == next_action)) { - // only read the translation if there is actually a next - // action - const char *translation = _(states[PackageOpsDone[pkg]].str); - std::string msg; - - // we moved from one dpkg state to a new one, report that - PackageOpsDone[pkg]++; - PackagesDone++; - - strprintf(msg, translation, i18n_pkgname.c_str()); - d->progress->StatusChanged(pkgname, PackagesDone, PackagesTotal, msg); - + char const * const next_action = states[PackageOpsDone[pkg]].state; + if (next_action && Debug == true) + std::clog << "(parsed from dpkg) pkg: " << short_pkgname + << " action: " << action << " (expected: '" << next_action << "' " + << PackageOpsDone[pkg] << " of " << states.size() << ")" << endl; + + // check if the package moved to the next dpkg state + if(next_action && (action == next_action)) + { + // only read the translation if there is actually a next action + char const * const translation = _(states[PackageOpsDone[pkg]].str); + + // we moved from one dpkg state to a new one, report that + ++PackageOpsDone[pkg]; + ++PackagesDone; + + std::string msg; + strprintf(msg, translation, i18n_pkgname.c_str()); + d->progress->StatusChanged(pkgname, PackagesDone, PackagesTotal, msg); + } } - if (Debug == true) - std::clog << "(parsed from dpkg) pkg: " << short_pkgname - << " action: " << action << endl; } } /*}}}*/ -- cgit v1.2.3 From 223ae57d468fdcac451209a095047a07a5698212 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 8 Sep 2014 21:05:11 +0200 Subject: rework PTY magic to fix stair-stepping on kfreebsd A pty slave we have got from openpty can only be used for one dpkg child, if we give it to a second child on kfreebsd setting TIOCSCTTY fails causing the output to be stair-stepped from now on. By switching the code to creating a master and opening a new slave in the child for each child we can fix this glitch, so that at least the master remains stable. Closes: 759684 --- apt-pkg/deb/dpkgpm.cc | 159 +++++++++++++++++++++++++++++++++----------------- apt-pkg/deb/dpkgpm.h | 1 + 2 files changed, 107 insertions(+), 53 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 5411d9ee8..04a13a86c 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -59,8 +59,8 @@ class pkgDPkgPMPrivate { public: pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0), - term_out(NULL), history_out(NULL), - progress(NULL), master(-1), slave(-1) + term_out(NULL), history_out(NULL), + progress(NULL), master(-1), slave(NULL) { dpkgbuf[0] = '\0'; } @@ -77,9 +77,9 @@ public: APT::Progress::PackageManager *progress; // pty stuff - struct termios tt; + struct termios tt; int master; - int slave; + char * slave; // signals sigset_t sigmask; @@ -510,7 +510,7 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf) return result; } /*}}}*/ -// DPkgPM::DoStdin - Read stdin and pass to slave pty /*{{{*/ +// DPkgPM::DoStdin - Read stdin and pass to master pty /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -1051,60 +1051,127 @@ void pkgDPkgPM::StartPtyMagic() { if (_config->FindB("Dpkg::Use-Pty", true) == false) { - d->master = d->slave = -1; + d->master = -1; + if (d->slave != NULL) + free(d->slave); + d->slave = NULL; return; } - // setup the pty and stuff - struct winsize win; - + _error->PushToStack(); // if tcgetattr for both stdin/stdout returns 0 (no error) // we do the pty magic - _error->PushToStack(); - if (tcgetattr(STDIN_FILENO, &d->tt) == 0 && - tcgetattr(STDOUT_FILENO, &d->tt) == 0) + if (tcgetattr(STDOUT_FILENO, &d->tt) == 0 && + tcgetattr(STDIN_FILENO, &d->tt) == 0) { - if (ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&win) < 0) - { - _error->Errno("ioctl", _("ioctl(TIOCGWINSZ) failed")); - } else if (openpty(&d->master, &d->slave, NULL, &d->tt, &win) < 0) - { - _error->Errno("openpty", _("Can not write log (%s)"), _("Is /dev/pts mounted?")); - d->master = d->slave = -1; - } else { - struct termios rtt; - rtt = d->tt; - cfmakeraw(&rtt); - rtt.c_lflag &= ~ECHO; - rtt.c_lflag |= ISIG; + d->master = posix_openpt(O_RDWR | O_NOCTTY); + if (d->master == -1) + _error->Errno("posix_openpt", _("Can not write log (%s)"), _("Is /dev/pts mounted?")); + else if (unlockpt(d->master) == -1) + { + _error->Errno("unlockpt", "Unlocking the slave of master fd %d failed!", d->master); + close(d->master); + d->master = -1; + } + else + { + char const * const slave_name = ptsname(d->master); + if (slave_name == NULL) + { + _error->Errno("unlockpt", "Getting name for slave of master fd %d failed!", d->master); + close(d->master); + d->master = -1; + } + else + { + d->slave = strdup(slave_name); + if (d->slave == NULL) + { + _error->Errno("strdup", "Copying name %s for slave of master fd %d failed!", slave_name, d->master); + close(d->master); + d->master = -1; + } + struct winsize win; + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) < 0) + _error->Errno("ioctl", "Getting TIOCGWINSZ from stdout failed!"); + if (ioctl(d->master, TIOCSWINSZ, &win) < 0) + _error->Errno("ioctl", "Setting TIOCSWINSZ for master fd %d failed!", d->master); + if (tcsetattr(d->master, TCSANOW, &d->tt) == -1) + _error->Errno("tcsetattr", "Setting in Start via TCSANOW for master fd %d failed!", d->master); + + struct termios raw_tt; + raw_tt = d->tt; + cfmakeraw(&raw_tt); + raw_tt.c_lflag &= ~ECHO; + raw_tt.c_lflag |= ISIG; // block SIGTTOU during tcsetattr to prevent a hang if // the process is a member of the background process group // http://www.opengroup.org/onlinepubs/000095399/functions/tcsetattr.html sigemptyset(&d->sigmask); sigaddset(&d->sigmask, SIGTTOU); sigprocmask(SIG_BLOCK,&d->sigmask, &d->original_sigmask); - tcsetattr(0, TCSAFLUSH, &rtt); - sigprocmask(SIG_SETMASK, &d->original_sigmask, 0); - } + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw_tt) == -1) + _error->Errno("tcsetattr", "Setting in Start via TCSAFLUSH for stdout failed!"); + sigprocmask(SIG_SETMASK, &d->original_sigmask, NULL); + } } - // complain only if stdout is either a terminal (but still failed) or is an invalid + } + else + { + // complain only if stdout is either a terminal (but still failed) or is an invalid // descriptor otherwise we would complain about redirection to e.g. /dev/null as well. - else if (isatty(STDOUT_FILENO) == 1 || errno == EBADF) - _error->Errno("tcgetattr", _("Can not write log (%s)"), _("Is stdout a terminal?")); + 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(); + if (_error->PendingError() == true) + { + if (d->master != -1) + { + close(d->master); + d->master = -1; + } + _error->DumpErrors(std::cerr); + } + _error->RevertToStack(); } +void pkgDPkgPM::SetupSlavePtyMagic() +{ + if(d->master == -1) + return; + + if (close(d->master) == -1) + _error->FatalE("close", "Closing master %d in child failed!", d->master); + if (setsid() == -1) + _error->FatalE("setsid", "Starting a new session for child failed!"); + + int const slaveFd = open(d->slave, O_RDWR); + if (slaveFd == -1) + _error->FatalE("open", _("Can not write log (%s)"), _("Is /dev/pts mounted?")); + if (ioctl(slaveFd, TIOCSCTTY, 0) < 0) + _error->FatalE("ioctl", "Setting TIOCSCTTY for slave fd %d failed!", slaveFd); + else + { + for (unsigned short i = 0; i < 3; ++i) + if (dup2(slaveFd, i) == -1) + _error->FatalE("dup2", "Dupping %d to %d in child failed!", slaveFd, i); + + if (tcsetattr(0, TCSANOW, &d->tt) < 0) + _error->FatalE("tcsetattr", "Setting in Setup via TCSANOW for slave fd %d failed!", slaveFd); + } +} void pkgDPkgPM::StopPtyMagic() { - if(d->slave > 0) - close(d->slave); + if (d->slave != NULL) + free(d->slave); + d->slave = NULL; if(d->master >= 0) { - tcsetattr(0, TCSAFLUSH, &d->tt); + if (tcsetattr(0, TCSAFLUSH, &d->tt) == -1) + _error->FatalE("tcsetattr", "Setting in Stop via TCSAFLUSH for stdin failed!"); close(d->master); + d->master = -1; } } @@ -1416,22 +1483,8 @@ bool pkgDPkgPM::GoNoABIBreak(APT::Progress::PackageManager *progress) pid_t Child = ExecFork(KeepFDs); if (Child == 0) { - // This is the child - if(d->slave >= 0 && d->master >= 0) - { - setsid(); - int res = ioctl(d->slave, TIOCSCTTY, 0); - if (res < 0) { - std::cerr << "ioctl(TIOCSCTTY) failed for fd: " - << d->slave << std::endl; - } else { - close(d->master); - dup2(d->slave, 0); - dup2(d->slave, 1); - dup2(d->slave, 2); - close(d->slave); - } - } + // This is the child + SetupSlavePtyMagic(); close(fd[0]); // close the read end of the pipe dpkgChrootDirectory(); diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h index 859c74b46..2c1805015 100644 --- a/apt-pkg/deb/dpkgpm.h +++ b/apt-pkg/deb/dpkgpm.h @@ -110,6 +110,7 @@ class pkgDPkgPM : public pkgPackageManager // helper void BuildPackagesProgressMap(); void StartPtyMagic(); + void SetupSlavePtyMagic(); void StopPtyMagic(); // input processing -- cgit v1.2.3