From d888846b68dd5fad998b84c5cb6246b1b63398cd Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman Date: Mon, 1 Dec 2025 02:51:37 +0300 Subject: [PATCH 1/4] libstore: Use makeTempPath in optimizePath_ This was intended to be cherry-picked in 6aed9d877cfbe1e649b69d2f15b6aeccbfbb0f3a, but was left hanging. This is actually important for fixing [^]. emilazy let me know of this bad cherry-pick and its significance. [^]: https://github.com/NixOS/nix/issues/7273 Originally fixed by Lily Ballard in https://gerrit.lix.systems/c/lix/+/2100. --- src/libstore/optimise-store.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstore/optimise-store.cc b/src/libstore/optimise-store.cc index dca093e04..3d8adedbf 100644 --- a/src/libstore/optimise-store.cc +++ b/src/libstore/optimise-store.cc @@ -234,7 +234,7 @@ void LocalStore::optimisePath_( its timestamp back to 0. */ MakeReadOnly makeReadOnly(mustToggle ? dirOfPath : ""); - std::filesystem::path tempLink = fmt("%1%/.tmp-link-%2%-%3%", config->realStoreDir, getpid(), rand()); + std::filesystem::path tempLink = makeTempPath(config->realStoreDir.get(), ".tmp-link"); try { std::filesystem::create_hard_link(linkPath, tempLink); From 1cc337bb5f7363a711d7bd7f4e28e2ecc54aa975 Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman Date: Mon, 1 Dec 2025 02:56:44 +0300 Subject: [PATCH 2/4] libstore: Actually correctly call remove in case rename fails --- src/libstore/optimise-store.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/libstore/optimise-store.cc b/src/libstore/optimise-store.cc index 3d8adedbf..d1e858300 100644 --- a/src/libstore/optimise-store.cc +++ b/src/libstore/optimise-store.cc @@ -255,8 +255,12 @@ void LocalStore::optimisePath_( try { std::filesystem::rename(tempLink, path); } catch (std::filesystem::filesystem_error & e) { - std::filesystem::remove(tempLink); - printError("unable to unlink %1%", tempLink); + { + std::error_code ec; + remove(tempLink, ec); /* Clean up after ourselves. */ + if (ec) + printError("unable to unlink %1%: %2%", tempLink, ec.message()); + } if (e.code() == std::errc::too_many_links) { /* Some filesystems generate too many links on the rename, rather than on the original link. (Probably it From bf7c53f2d3e665720c371167b8934d50e818656b Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman Date: Mon, 1 Dec 2025 03:00:45 +0300 Subject: [PATCH 3/4] libutil: Propagate error code in createSymlink --- src/libutil/file-system.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/libutil/file-system.cc b/src/libutil/file-system.cc index 6b145b343..9e27940c5 100644 --- a/src/libutil/file-system.cc +++ b/src/libutil/file-system.cc @@ -737,11 +737,10 @@ std::filesystem::path makeTempPath(const std::filesystem::path & root, const std void createSymlink(const Path & target, const Path & link) { - try { - std::filesystem::create_symlink(target, link); - } catch (std::filesystem::filesystem_error & e) { - throw SysError("creating symlink '%1%' -> '%2%'", link, target); - } + std::error_code ec; + std::filesystem::create_symlink(target, link, ec); + if (ec) + throw SysError(ec.value(), "creating symlink '%1%' -> '%2%'", link, target); } void replaceSymlink(const std::filesystem::path & target, const std::filesystem::path & link) From 40e3f5c0a471075d02e258e950c0f2c931b36177 Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman Date: Mon, 1 Dec 2025 03:09:20 +0300 Subject: [PATCH 4/4] libutil: Make AutoDelete non-copyable and non-movable This is a good precaution, since we don't want to delete directories twice accidentally. --- src/libutil/include/nix/util/file-system.hh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libutil/include/nix/util/file-system.hh b/src/libutil/include/nix/util/file-system.hh index 7673c24fd..d8b266e02 100644 --- a/src/libutil/include/nix/util/file-system.hh +++ b/src/libutil/include/nix/util/file-system.hh @@ -294,6 +294,10 @@ class AutoDelete public: AutoDelete(); AutoDelete(const std::filesystem::path & p, bool recursive = true); + AutoDelete(AutoDelete &&) = delete; + AutoDelete(const AutoDelete &) = delete; + AutoDelete & operator=(AutoDelete &&) = delete; + AutoDelete & operator=(const AutoDelete &) = delete; ~AutoDelete(); void cancel();