diff options
| author | Julian Andres Klode <jak@debian.org> | 2024-11-22 16:12:34 +0000 |
|---|---|---|
| committer | Julian Andres Klode <jak@debian.org> | 2024-11-22 16:12:34 +0000 |
| commit | 1818699c1bc8a5be2d6542fe3212f26af7fa912a (patch) | |
| tree | c6a6312c088d5367d803a884b99246aaff05e9c3 /methods/copy.cc | |
| parent | f9069c2498f74c09b4a4d7da8bb677756b371dae (diff) | |
| parent | 7adf8c1fa8d519b8b57292763eb7703e7d3cc580 (diff) | |
Merge branch 'fix/partialfilemirror' into 'main'
Support uncompressed indexes from partial file:/ mirrors
See merge request apt-team/apt!235
Diffstat (limited to 'methods/copy.cc')
| -rw-r--r-- | methods/copy.cc | 90 |
1 files changed, 53 insertions, 37 deletions
diff --git a/methods/copy.cc b/methods/copy.cc index 44205e4cd..9c9c6572d 100644 --- a/methods/copy.cc +++ b/methods/copy.cc @@ -26,7 +26,7 @@ class CopyMethod final : public aptMethod { - virtual bool Fetch(FetchItem *Itm) APT_OVERRIDE; + bool URIAcquire(std::string const &Message, FetchItem *Itm) APT_OVERRIDE; public: CopyMethod() : aptMethod("copy", "1.0", SingleInstance | SendConfig | SendURIEncoded) @@ -36,55 +36,71 @@ class CopyMethod final : public aptMethod }; // CopyMethod::Fetch - Fetch a file /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool CopyMethod::Fetch(FetchItem *Itm) +bool CopyMethod::URIAcquire(std::string const &Message, FetchItem *Itm) { - // this ensures that relative paths work in copy - std::string const File = DecodeSendURI(Itm->Uri.substr(Itm->Uri.find(':')+1)); - - // Stat the file and send a start message - struct stat Buf; - if (stat(File.c_str(),&Buf) != 0) - return _error->Errno("stat",_("Failed to stat")); + struct FileCopyType { + std::string name; + struct stat stat{}; + explicit FileCopyType(std::string &&file) : name{std::move(file)} {} + }; + std::vector<FileCopyType> files; + // this ensures that relative paths work + files.emplace_back(DecodeSendURI(Itm->Uri.substr(Itm->Uri.find(':')+1))); + for (auto const &AltPath : VectorizeString(LookupTag(Message, "Alternate-Paths"), '\n')) + files.emplace_back(CombineWithAlternatePath(flNotFile(files[0].name), DecodeSendURI(AltPath))); + files.erase(std::remove_if(files.begin(), files.end(), [](auto &file) + { return stat(file.name.c_str(), &file.stat) != 0; }), + files.end()); + if (files.empty()) + return _error->Errno("copy-stat", _("Failed to stat")); // Forumulate a result and send a start message FetchResult Res; - Res.Size = Buf.st_size; Res.Filename = Itm->DestFile; - Res.LastModified = Buf.st_mtime; Res.IMSHit = false; - URIStart(Res); - // just calc the hashes if the source and destination are identical - if (File == Itm->DestFile || Itm->DestFile == "/dev/null") + for (auto const &File : files) { + Res.Size = File.stat.st_size; + Res.LastModified = File.stat.st_mtime; + + // just calc the hashes if the source and destination are identical + if (Itm->DestFile == "/dev/null" || File.name == Itm->DestFile) + { + URIStart(Res); + CalculateHashes(Itm, Res); + URIDone(Res); + return true; + } + + FileFd From(File.name, FileFd::ReadOnly); + FileFd To(Itm->DestFile, FileFd::WriteAtomic); + To.EraseOnFailure(); + if (not From.IsOpen() || not To.IsOpen()) + continue; + + // Copy the file + URIStart(Res); + if (not CopyFile(From, To)) + { + To.OpFail(); + continue; + } + From.Close(); + To.Close(); + CalculateHashes(Itm, Res); - URIDone(Res); - return true; - } + if (not Itm->ExpectedHashes.empty() && Itm->ExpectedHashes != Res.Hashes) + continue; - // See if the file exists - FileFd From(File,FileFd::ReadOnly); - FileFd To(Itm->DestFile,FileFd::WriteAtomic); - To.EraseOnFailure(); + if (not TransferModificationTimes(File.name.c_str(), Res.Filename.c_str(), Res.LastModified)) + continue; - // Copy the file - if (CopyFile(From,To) == false) - { - To.OpFail(); - return false; + URIDone(Res); + return true; } - From.Close(); - To.Close(); - - if (TransferModificationTimes(File.c_str(), Res.Filename.c_str(), Res.LastModified) == false) - return false; - - CalculateHashes(Itm, Res); - URIDone(Res); - return true; + return false; } /*}}}*/ |
