From 48cbc5413fb2a0e490c2282b9df65da96ad7a9f2 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 17 May 2023 17:18:33 +0200 Subject: Seed snapshot servers for well-known hosts This will attempt to fallback to a per-server setting if we could not determine a value from the release file. --- apt-pkg/deb/debmetaindex.cc | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) (limited to 'apt-pkg/deb') diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 4133540ab..ddc246349 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -1295,20 +1295,42 @@ class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type /*{{{*/ Options.emplace("SHADOWED", "true"); + ::URI ArchiveURI(URI); + // Trim trailing and leading / from the path because we don't want them when calculating snapshot url + if (not ArchiveURI.Path.empty() && ArchiveURI.Path[ArchiveURI.Path.length() - 1] == '/') + ArchiveURI.Path.erase(ArchiveURI.Path.length() - 1); + if (not ArchiveURI.Path.empty() && ArchiveURI.Path[0] == '/') + ArchiveURI.Path.erase(0, 1); + std::string Server; + auto const Deb = GetDebReleaseIndexBy(List, URI, Dist, Options); std::string filename; - if (not ReleaseFileName(Deb, filename)) - return _error->Error("Cannot identify snapshot server for %s %s - run update without snapshot id first", URI.c_str(), Dist.c_str()); - auto OldDeb = dynamic_cast(Deb->UnloadedClone()); - if (not OldDeb->Load(filename, nullptr)) - return _error->Error("Cannot identify snapshot server for %s %s - run update without snapshot id first", URI.c_str(), Dist.c_str()); - auto Server = SnapshotServer(OldDeb); - delete OldDeb; + // The Release file and config based on that should be the ultimate source of truth. + if (ReleaseFileName(Deb, filename)) + { + auto OldDeb = dynamic_cast(Deb->UnloadedClone()); + if (not OldDeb->Load(filename, nullptr)) + return _error->Error("Cannot identify snapshot server for %s %s - run update without snapshot id first", URI.c_str(), Dist.c_str()); + Server = SnapshotServer(OldDeb); + delete OldDeb; + } if (Server.empty()) + { + // We did not find a server based on the release file. + // Lookup a fallback based on the host. For a.b.c, this will try a.b.c, .b.c, and .c to allow generalization for cc.archive.ubuntu.com + for (std::string Host = ArchiveURI.Host; not Host.empty() && Server.empty(); Host = Host.find(".", 1) != Host.npos ? Host.substr(Host.find(".", 1)) : "") + Server = _config->Find("Acquire::Snapshots::URI::Host::" + Host); + if (Server == "no") + Server = ""; + } + if (Server.empty()) + { + if (filename.empty()) + return _error->Error("Cannot identify snapshot server for %s %s - run update without snapshot id first", URI.c_str(), Dist.c_str()); return _error->Error("Snapshots not supported for %s %s", URI.c_str(), Dist.c_str()); - - auto SnapshotURI = SubstVar(Server, "@SNAPSHOTID@", Snapshot); + } + auto SnapshotURI = SubstVar(SubstVar(Server, "@SNAPSHOTID@", Snapshot), "@PATH@", ArchiveURI.Path); if (not CreateItemInternalOne(List, SnapshotURI, Dist, Section, IsSrc, SnapshotOptions)) return false; -- cgit v1.2.3-70-g09d2 From 4e35e5079f589700b4b5f1fc00787144bc1c58bf Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 24 May 2023 11:07:26 +0200 Subject: Ensure that Snapshots: no doesn't get overriden by host-name config --- apt-pkg/deb/debmetaindex.cc | 10 +++------- test/integration/test-snapshot | 4 ++++ 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'apt-pkg/deb') diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index ddc246349..4bd7dfa78 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -1261,9 +1261,7 @@ class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type /*{{{*/ #define APT_EMPTY_SERVER \ if (server.empty() == false) \ { \ - if (server != "no") \ - return server; \ - return ""; \ + return server; \ } #define APT_CHECK_SERVER(X, Y) \ if (not Rls->Get##X().empty()) \ @@ -1321,12 +1319,10 @@ class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type /*{{{*/ // Lookup a fallback based on the host. For a.b.c, this will try a.b.c, .b.c, and .c to allow generalization for cc.archive.ubuntu.com for (std::string Host = ArchiveURI.Host; not Host.empty() && Server.empty(); Host = Host.find(".", 1) != Host.npos ? Host.substr(Host.find(".", 1)) : "") Server = _config->Find("Acquire::Snapshots::URI::Host::" + Host); - if (Server == "no") - Server = ""; } - if (Server.empty()) + if (Server.empty() || Server == "no") { - if (filename.empty()) + if (Server != "no" && filename.empty()) return _error->Error("Cannot identify snapshot server for %s %s - run update without snapshot id first", URI.c_str(), Dist.c_str()); return _error->Error("Snapshots not supported for %s %s", URI.c_str(), Dist.c_str()); } diff --git a/test/integration/test-snapshot b/test/integration/test-snapshot index e32b91daf..2bf7d70d4 100755 --- a/test/integration/test-snapshot +++ b/test/integration/test-snapshot @@ -173,6 +173,10 @@ testfailuremsg "E: Snapshots not supported for http://localhost:${APTHTTPPORT}/ E: Snapshots not supported for http://localhost:${APTHTTPPORT}/ stable E: The list of sources could not be read." aptget update --print-uris -S BANANA +testfailuremsg "E: Snapshots not supported for http://localhost:${APTHTTPPORT}/ stable +E: Snapshots not supported for http://localhost:${APTHTTPPORT}/ stable +E: The list of sources could not be read." aptget update --print-uris -S BANANA -o Acquire::Snapshots::URI::Host::localhost="https://example.org/snapshots/@PATH@/@SNAPSHOTID@/" + msgmsg "Snapshot URI configured in apt.conf" sed -i '/^Snapshots: / d' $(find rootdir/var/lib/apt/lists -name '*Release') releasechanger 'Label' 'Testcases' -- cgit v1.2.3-70-g09d2 From 4000ee2f9064623e096d975489aec35c99982437 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 24 May 2023 11:22:34 +0200 Subject: Rework the domain iteration in the host fallback Separate the determination of the next level domain into its own function and split out the "we found a result" into its own break for improved readability. --- apt-pkg/deb/debmetaindex.cc | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'apt-pkg/deb') diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 4bd7dfa78..ef6bce261 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -1283,6 +1283,16 @@ class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type /*{{{*/ #undef APT_EMPTY_SERVER return ""; } + + /// \brief Given a hostname, strip one level down, e.g. a.b.c -> .b.c -> .c, this + /// allows you to match a.b.c against itself, .b.c, and .c, but not b.c + static inline std::string NextLevelDomain(std::string Host) + { + auto nextDot = Host.find(".", 1); + if (nextDot == Host.npos) + return ""; + return Host.substr(nextDot); + } bool CreateItemInternal(std::vector &List, std::string URI, std::string const &Dist, std::string const &Section, bool const &IsSrc, std::map Options) const @@ -1313,12 +1323,17 @@ class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type /*{{{*/ Server = SnapshotServer(OldDeb); delete OldDeb; } + // We did not find a server based on the release file. + // Lookup a fallback based on the host. For a.b.c, this will + // try a.b.c, .b.c, and .c to allow generalization for cc.archive.ubuntu.com if (Server.empty()) { - // We did not find a server based on the release file. - // Lookup a fallback based on the host. For a.b.c, this will try a.b.c, .b.c, and .c to allow generalization for cc.archive.ubuntu.com - for (std::string Host = ArchiveURI.Host; not Host.empty() && Server.empty(); Host = Host.find(".", 1) != Host.npos ? Host.substr(Host.find(".", 1)) : "") + for (std::string Host = ArchiveURI.Host; not Host.empty(); Host = NextLevelDomain(Host)) + { Server = _config->Find("Acquire::Snapshots::URI::Host::" + Host); + if (not Server.empty()) + break; + } } if (Server.empty() || Server == "no") { -- cgit v1.2.3-70-g09d2