From f2c087449286812823d06d1b560fa947e438fa0d Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 2 Dec 2020 15:51:09 +0100 Subject: Guess compressor only if no AR nember with exact name exists Explicitly opening a tar member is a bit harder than it needs to be as you have to remove the compressor extension so that it can be guessed here gain potentially choosing the wrong member. Doesn't really matter for deb packages of course as the member count is pretty low and strongly defined, but testing is easier this way. It also finally fixes an incorrectly formatted error message. --- apt-pkg/deb/debfile.cc | 59 ++++++++++++++++++------------- test/integration/test-apt-get-install-deb | 2 +- 2 files changed, 35 insertions(+), 26 deletions(-) diff --git a/apt-pkg/deb/debfile.cc b/apt-pkg/deb/debfile.cc index bef0cd0d8..645a579ef 100644 --- a/apt-pkg/deb/debfile.cc +++ b/apt-pkg/deb/debfile.cc @@ -24,9 +24,12 @@ #include #include #include +#include #include +#include #include +#include #include #include #include @@ -105,42 +108,48 @@ const ARArchive::Member *debDebFile::GotoMember(const char *Name) /* Simple wrapper around tar.. */ bool debDebFile::ExtractTarMember(pkgDirStream &Stream,const char *Name) { - // Get the archive member - const ARArchive::Member *Member = NULL; std::string Compressor; + auto const Compressors = APT::Configuration::getCompressors(); - std::vector compressor = APT::Configuration::getCompressors(); - for (std::vector::const_iterator c = compressor.begin(); - c != compressor.end(); ++c) + ARArchive::Member const *Member = AR.FindMember(Name); + if (Member != nullptr) { - Member = AR.FindMember(std::string(Name).append(c->Extension).c_str()); - if (Member == NULL) - continue; - Compressor = c->Name; - break; + auto const found = std::find_if(Compressors.cbegin(), Compressors.cend(), [&](auto const &c) { + return not c.Extension.empty() && APT::String::Endswith(Name, c.Extension); + }); + if (found != Compressors.cend()) + Compressor = found->Name; } - - if (Member == NULL) - Member = AR.FindMember(std::string(Name).c_str()); - - if (Member == NULL) + else { - std::string ext = std::string(Name) + ".{"; - for (std::vector::const_iterator c = compressor.begin(); - c != compressor.end(); ++c) { - if (!c->Extension.empty()) - ext.append(c->Extension.substr(1)); + for (auto const &c : Compressors) + { + if (c.Extension.empty()) + continue; + Member = AR.FindMember(std::string(Name).append(c.Extension).c_str()); + if (Member == nullptr) + continue; + Compressor = c.Name; + break; } - ext.append("}"); - return _error->Error(_("Internal error, could not locate member %s"), ext.c_str()); } - if (File.Seek(Member->Start) == false) + if (Member == nullptr) + { + std::ostringstream ext; + ext << Name << '{'; + for (auto const &c : Compressors) + if (not c.Extension.empty()) + ext << c.Extension << ','; + ext << '}'; + return _error->Error(_("Internal error, could not locate member %s"), ext.str().c_str()); + } + + if (not File.Seek(Member->Start)) return false; - // Prepare Tar ExtractTar Tar(File,Member->Size,Compressor); - if (_error->PendingError() == true) + if (_error->PendingError()) return false; return Tar.Go(Stream); } diff --git a/test/integration/test-apt-get-install-deb b/test/integration/test-apt-get-install-deb index 7fa5ca3e7..6fde00708 100755 --- a/test/integration/test-apt-get-install-deb +++ b/test/integration/test-apt-get-install-deb @@ -23,7 +23,7 @@ mv foo.rpm foo.deb for exe in apt aptget; do for cmd in install remove purge upgrade full-upgrade; do testfailuremsg "E: Invalid archive signature -E: Internal error, could not locate member control.tar.{zstlz4gzxzbz2lzma} +E: Internal error, could not locate member control.tar{.zst,.lz4,.gz,.xz,.bz2,.lzma,} E: Could not read meta data from ${TMPWORKINGDIRECTORY}/foo.deb E: The package lists or status file could not be parsed or opened." $exe $cmd ./foo.deb done -- cgit v1.2.3-18-g5258