diff options
Diffstat (limited to 'apt-pkg')
-rw-r--r-- | apt-pkg/acquire-item.cc | 177 | ||||
-rw-r--r-- | apt-pkg/acquire-item.h | 11 | ||||
-rw-r--r-- | apt-pkg/aptconfiguration.cc | 2 | ||||
-rw-r--r-- | apt-pkg/deb/debmetaindex.cc | 40 | ||||
-rw-r--r-- | apt-pkg/indexfile.cc | 1 | ||||
-rw-r--r-- | apt-pkg/indexfile.h | 1 |
6 files changed, 124 insertions, 108 deletions
diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 82ccaff64..7c7a204c4 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -85,32 +85,16 @@ static std::string GetKeepCompressedFileName(std::string file, IndexTarget const if (Target.KeepCompressed == false) return file; - std::string const CompressionTypes = Target.Option(IndexTarget::COMPRESSIONTYPES); - if (CompressionTypes.empty() == false) + std::string const KeepCompressedAs = Target.Option(IndexTarget::KEEPCOMPRESSEDAS); + if (KeepCompressedAs.empty() == false) { - std::string const ext = CompressionTypes.substr(0, CompressionTypes.find(' ')); + std::string const ext = KeepCompressedAs.substr(0, KeepCompressedAs.find(' ')); if (ext != "uncompressed") file.append(".").append(ext); } return file; } /*}}}*/ -static std::string GetCompressedFileName(IndexTarget const &Target, std::string const &Name, std::string const &Ext) /*{{{*/ -{ - if (Ext.empty() || Ext == "uncompressed") - return Name; - - // do not reverify cdrom sources as apt-cdrom may rewrite the Packages - // file when its doing the indexcopy - if (Target.URI.substr(0,6) == "cdrom:") - return Name; - - // adjust DestFile if its compressed on disk - if (Target.KeepCompressed == true) - return Name + '.' + Ext; - return Name; -} - /*}}}*/ static std::string GetMergeDiffsPatchFileName(std::string const &Final, std::string const &Patch)/*{{{*/ { // rred expects the patch as $FinalFile.ed.$patchname.gz @@ -326,7 +310,7 @@ std::string pkgAcqDiffIndex::GetFinalFilename() const std::string pkgAcqIndex::GetFinalFilename() const { std::string const FinalFile = GetFinalFileNameFromURI(Target.URI); - return GetCompressedFileName(Target, FinalFile, CurrentCompressionExtension); + return GetKeepCompressedFileName(FinalFile, Target); } std::string pkgAcqMetaSig::GetFinalFilename() const { @@ -379,7 +363,30 @@ bool pkgAcqTransactionItem::TransactionState(TransactionStates const state) case TransactionCommit: if(PartialFile.empty() == false) { - if (PartialFile != DestFile) + bool sameFile = (PartialFile == DestFile); + // we use symlinks on IMS-Hit to avoid copies + if (RealFileExists(DestFile)) + { + struct stat Buf; + if (lstat(PartialFile.c_str(), &Buf) != -1) + { + if (S_ISLNK(Buf.st_mode) && Buf.st_size > 0) + { + char partial[Buf.st_size + 1]; + ssize_t const sp = readlink(PartialFile.c_str(), partial, Buf.st_size); + if (sp == -1) + _error->Errno("pkgAcqTransactionItem::TransactionState-sp", _("Failed to readlink %s"), PartialFile.c_str()); + else + { + partial[sp] = '\0'; + sameFile = (DestFile == partial); + } + } + } + else + _error->Errno("pkgAcqTransactionItem::TransactionState-stat", _("Failed to stat %s"), PartialFile.c_str()); + } + if (sameFile == false) { // ensure that even without lists-cleanup all compressions are nuked std::string FinalFile = GetFinalFileNameFromURI(Target.URI); @@ -2621,20 +2628,6 @@ void pkgAcqIndex::Failed(string const &Message,pkgAcquire::MethodConfig const * TransactionManager->AbortTransaction(); } /*}}}*/ -// AcqIndex::ReverifyAfterIMS - Reverify index after an ims-hit /*{{{*/ -void pkgAcqIndex::ReverifyAfterIMS() -{ - // update destfile to *not* include the compression extension when doing - // a reverify (as its uncompressed on disk already) - DestFile = GetCompressedFileName(Target, GetPartialFileNameFromURI(Target.URI), CurrentCompressionExtension); - - // copy FinalFile into partial/ so that we check the hash again - string FinalFile = GetFinalFilename(); - Stage = STAGE_DECOMPRESS_AND_VERIFY; - Desc.URI = "copy:" + FinalFile; - QueueURI(Desc); -} - /*}}}*/ // AcqIndex::Done - Finished a fetch /*{{{*/ // --------------------------------------------------------------------- /* This goes through a number of states.. On the initial fetch the @@ -2651,107 +2644,93 @@ void pkgAcqIndex::Done(string const &Message, switch(Stage) { case STAGE_DOWNLOAD: - StageDownloadDone(Message, Hashes, Cfg); + StageDownloadDone(Message); break; case STAGE_DECOMPRESS_AND_VERIFY: - StageDecompressDone(Message, Hashes, Cfg); + StageDecompressDone(); break; } } /*}}}*/ // AcqIndex::StageDownloadDone - Queue for decompress and verify /*{{{*/ -void pkgAcqIndex::StageDownloadDone(string const &Message, HashStringList const &, - pkgAcquire::MethodConfig const * const) +void pkgAcqIndex::StageDownloadDone(string const &Message) { + Local = true; Complete = true; - // Handle the unzipd case - std::string FileName = LookupTag(Message,"Alt-Filename"); - if (FileName.empty() == false) + std::string const AltFilename = LookupTag(Message,"Alt-Filename"); + std::string Filename = LookupTag(Message,"Filename"); + + // we need to verify the file against the current Release file again + // on if-modfied-since hit to avoid a stale attack against us + if(StringToBool(LookupTag(Message,"IMS-Hit"),false) == true) { + // copy FinalFile into partial/ so that we check the hash again + string const FinalFile = GetExistingFilename(GetFinalFileNameFromURI(Target.URI)); + if (symlink(FinalFile.c_str(), DestFile.c_str()) != 0) + _error->WarningE("pkgAcqIndex::StageDownloadDone", "Symlinking final file %s back to %s failed", FinalFile.c_str(), DestFile.c_str()); + else + { + EraseFileName = DestFile; + Filename = DestFile; + } Stage = STAGE_DECOMPRESS_AND_VERIFY; - Local = true; - if (CurrentCompressionExtension != "uncompressed") - DestFile.erase(DestFile.length() - (CurrentCompressionExtension.length() + 1)); - Desc.URI = "copy:" + FileName; + Desc.URI = "store:" + Filename; QueueURI(Desc); - SetActiveSubprocess("copy"); + SetActiveSubprocess(::URI(Desc.URI).Access); return; } - FileName = LookupTag(Message,"Filename"); - + // methods like file:// give us an alternative (uncompressed) file + else if (Target.KeepCompressed == false && AltFilename.empty() == false) + { + if (CurrentCompressionExtension != "uncompressed") + DestFile.erase(DestFile.length() - (CurrentCompressionExtension.length() + 1)); + Filename = AltFilename; + } // Methods like e.g. "file:" will give us a (compressed) FileName that is // not the "DestFile" we set, in this case we uncompress from the local file - if (FileName != DestFile && RealFileExists(DestFile) == false) + else if (Filename != DestFile && RealFileExists(DestFile) == false) { - Local = true; - if (Target.KeepCompressed == true) - { - // but if we don't keep the uncompress we copy the compressed file first - Stage = STAGE_DOWNLOAD; - Desc.URI = "copy:" + FileName; - QueueURI(Desc); - SetActiveSubprocess("copy"); - return; - } + // symlinking ensures that the filename can be used for compression detection + // that is e.g. needed for by-hash which has no extension over file + if (symlink(Filename.c_str(),DestFile.c_str()) != 0) + _error->WarningE("pkgAcqIndex::StageDownloadDone", "Symlinking file %s to %s failed", Filename.c_str(), DestFile.c_str()); else { - // symlinking ensures that the filename can be used for compression detection - // that is e.g. needed for by-hash over file - if (symlink(FileName.c_str(),DestFile.c_str()) != 0) - _error->WarningE("pkgAcqIndex::StageDownloadDone", "Symlinking file %s to %s failed", FileName.c_str(), DestFile.c_str()); - else - { - EraseFileName = DestFile; - FileName = DestFile; - } + EraseFileName = DestFile; + Filename = DestFile; } } - else - EraseFileName = FileName; - - // we need to verify the file against the current Release file again - // on if-modfied-since hit to avoid a stale attack against us - if(StringToBool(LookupTag(Message,"IMS-Hit"),false) == true) - { - // The files timestamp matches, reverify by copy into partial/ - EraseFileName = ""; - ReverifyAfterIMS(); - return; - } - string decompProg = "store"; - if (Target.KeepCompressed == true) - { - DestFile = "/dev/null"; - EraseFileName.clear(); - } + Stage = STAGE_DECOMPRESS_AND_VERIFY; + DestFile = GetKeepCompressedFileName(GetPartialFileNameFromURI(Target.URI), Target); + if (Filename != DestFile && flExtension(Filename) == flExtension(DestFile)) + Desc.URI = "copy:" + Filename; else + Desc.URI = "store:" + Filename; + if (DestFile == Filename) { if (CurrentCompressionExtension == "uncompressed") - decompProg = "copy"; - else - DestFile.erase(DestFile.length() - (CurrentCompressionExtension.length() + 1)); + return StageDecompressDone(); + DestFile = "/dev/null"; } + if (EraseFileName.empty()) + EraseFileName = Filename; + // queue uri for the next stage - Stage = STAGE_DECOMPRESS_AND_VERIFY; - Desc.URI = decompProg + ":" + FileName; QueueURI(Desc); - SetActiveSubprocess(decompProg); + SetActiveSubprocess(::URI(Desc.URI).Access); } /*}}}*/ // AcqIndex::StageDecompressDone - Final verification /*{{{*/ -void pkgAcqIndex::StageDecompressDone(string const &, - HashStringList const &, - pkgAcquire::MethodConfig const * const) +void pkgAcqIndex::StageDecompressDone() { - if (Target.KeepCompressed == true && DestFile == "/dev/null") - DestFile = GetPartialFileNameFromURI(Target.URI + '.' + CurrentCompressionExtension); + if (DestFile == "/dev/null") + DestFile = GetKeepCompressedFileName(GetPartialFileNameFromURI(Target.URI), Target); // Done, queue for rename on transaction finished TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename()); - return; } /*}}}*/ pkgAcqIndex::~pkgAcqIndex() {} diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index 93ff0a9c3..306b1772a 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -914,16 +914,12 @@ class APT_HIDDEN pkgAcqIndex : public pkgAcqBaseIndex AllStages Stage; /** \brief Handle what needs to be done when the download is done */ - void StageDownloadDone(std::string const &Message, - HashStringList const &Hashes, - pkgAcquire::MethodConfig const * const Cfg); + void StageDownloadDone(std::string const &Message); /** \brief Handle what needs to be done when the decompression/copy is * done */ - void StageDecompressDone(std::string const &Message, - HashStringList const &Hashes, - pkgAcquire::MethodConfig const * const Cfg); + void StageDecompressDone(); /** \brief If \b set, this partially downloaded file will be * removed when the download completes. @@ -941,9 +937,6 @@ class APT_HIDDEN pkgAcqIndex : public pkgAcqBaseIndex /** \brief Do the changes needed to fetch via AptByHash (if needed) */ void InitByHashIfNeeded(); - /** \brief Schedule file for verification after a IMS hit */ - void ReverifyAfterIMS(); - /** \brief Get the full pathname of the final file for the current URI */ virtual std::string GetFinalFilename() const APT_OVERRIDE; diff --git a/apt-pkg/aptconfiguration.cc b/apt-pkg/aptconfiguration.cc index 53f29df79..01ae5a642 100644 --- a/apt-pkg/aptconfiguration.cc +++ b/apt-pkg/aptconfiguration.cc @@ -37,6 +37,7 @@ static void setDefaultConfigurationForCompressors() { // Set default application paths to check for optional compression types _config->CndSet("Dir::Bin::bzip2", "/bin/bzip2"); _config->CndSet("Dir::Bin::xz", "/usr/bin/xz"); + _config->CndSet("Dir::Bin::lz4", "/usr/bin/lz4"); if (FileExists(_config->FindFile("Dir::Bin::xz")) == true) { _config->Set("Dir::Bin::lzma", _config->FindFile("Dir::Bin::xz")); _config->Set("APT::Compressor::lzma::Binary", "xz"); @@ -79,6 +80,7 @@ const Configuration::getCompressionTypes(bool const &Cached) { _config->CndSet("Acquire::CompressionTypes::bz2","bzip2"); _config->CndSet("Acquire::CompressionTypes::lzma","lzma"); _config->CndSet("Acquire::CompressionTypes::gz","gzip"); + _config->CndSet("Acquire::CompressionTypes::lz4","lz4"); setDefaultConfigurationForCompressors(); std::vector<APT::Configuration::Compressor> const compressors = getCompressors(); diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 46a9f9c97..2521fccd6 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -138,6 +138,21 @@ static void GetIndexTargetsFor(char const * const Type, std::string const &URI, DefCompressionTypes = os.str(); } } + std::string DefKeepCompressedAs; + { + std::vector<APT::Configuration::Compressor> comps = APT::Configuration::getCompressors(); + if (comps.empty() == false) + { + std::sort(comps.begin(), comps.end(), + [](APT::Configuration::Compressor const &a, APT::Configuration::Compressor const &b) { return a.Cost < b.Cost; }); + std::ostringstream os; + for (auto const &c : comps) + if (c.Cost != 0) + os << c.Extension.substr(1) << ' '; + DefKeepCompressedAs = os.str(); + } + DefKeepCompressedAs += "uncompressed"; + } std::string const NativeArch = _config->Find("APT::Architecture"); bool const GzipIndex = _config->FindB("Acquire::GzipIndexes", false); for (std::vector<debReleaseIndexPrivate::debSectionEntry>::const_iterator E = entries.begin(); E != entries.end(); ++E) @@ -155,11 +170,35 @@ static void GetIndexTargetsFor(char const * const Type, std::string const &URI, bool const UsePDiffs = APT_T_CONFIG_BOOL("PDiffs", E->UsePDiffs); std::string const UseByHash = APT_T_CONFIG_STR("By-Hash", E->UseByHash); std::string const CompressionTypes = APT_T_CONFIG_STR("CompressionTypes", DefCompressionTypes); + std::string KeepCompressedAs = APT_T_CONFIG_STR("KeepCompressedAs", ""); #undef APT_T_CONFIG_BOOL #undef APT_T_CONFIG_STR if (tplMetaKey.empty()) continue; + if (KeepCompressedAs.empty()) + KeepCompressedAs = DefKeepCompressedAs; + else + { + std::vector<std::string> const defKeep = VectorizeString(DefKeepCompressedAs, ' '); + std::vector<std::string> const valKeep = VectorizeString(KeepCompressedAs, ' '); + std::vector<std::string> keep; + for (auto const &val : valKeep) + { + if (val.empty()) + continue; + if (std::find(defKeep.begin(), defKeep.end(), val) == defKeep.end()) + continue; + keep.push_back(val); + } + if (std::find(keep.begin(), keep.end(), "uncompressed") == keep.end()) + keep.push_back("uncompressed"); + std::ostringstream os; + std::copy(keep.begin(), keep.end()-1, std::ostream_iterator<std::string>(os, " ")); + os << *keep.rbegin(); + KeepCompressedAs = os.str(); + } + for (std::vector<std::string>::const_iterator L = E->Languages.begin(); L != E->Languages.end(); ++L) { if (*L == "none" && tplMetaKey.find("$(LANGUAGE)") != std::string::npos) @@ -253,6 +292,7 @@ static void GetIndexTargetsFor(char const * const Type, std::string const &URI, Options.insert(std::make_pair("BY_HASH", UseByHash)); Options.insert(std::make_pair("DEFAULTENABLED", DefaultEnabled ? "yes" : "no")); Options.insert(std::make_pair("COMPRESSIONTYPES", CompressionTypes)); + Options.insert(std::make_pair("KEEPCOMPRESSEDAS", KeepCompressedAs)); Options.insert(std::make_pair("SOURCESENTRY", E->sourcesEntry)); bool IsOpt = IsOptional; diff --git a/apt-pkg/indexfile.cc b/apt-pkg/indexfile.cc index f0fae907f..dfd482c04 100644 --- a/apt-pkg/indexfile.cc +++ b/apt-pkg/indexfile.cc @@ -144,6 +144,7 @@ std::string IndexTarget::Option(OptionKeys const EnumKey) const /*{{{*/ APT_CASE(COMPRESSIONTYPES); APT_CASE(SOURCESENTRY); APT_CASE(BY_HASH); + APT_CASE(KEEPCOMPRESSEDAS); #undef APT_CASE case FILENAME: return _config->FindDir("Dir::State::lists") + URItoFileName(URI); case EXISTING_FILENAME: diff --git a/apt-pkg/indexfile.h b/apt-pkg/indexfile.h index f87693a8f..5c666671c 100644 --- a/apt-pkg/indexfile.h +++ b/apt-pkg/indexfile.h @@ -90,6 +90,7 @@ class IndexTarget /*{{{*/ DEFAULTENABLED, SOURCESENTRY, BY_HASH, + KEEPCOMPRESSEDAS, }; std::string Option(OptionKeys const Key) const; bool OptionBool(OptionKeys const Key) const; |