diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc index f7f3204a4..e45f5af81 100644 --- a/src/libstore/build/local-derivation-goal.cc +++ b/src/libstore/build/local-derivation-goal.cc @@ -16,6 +16,7 @@ #include "cgroup.hh" #include "personality.hh" #include "namespaces.hh" +#include "file-system.hh" #include #include @@ -2116,10 +2117,11 @@ void LocalDerivationGoal::runChild() /* The tmpDir in scope points at the temporary build directory for our derivation. Some packages try different mechanisms to find temporary directories, so we want to open up a broader place for them to dump their files, if needed. */ - Path globalTmpDir = canonPath(getEnvNonEmpty("TMPDIR").value_or("/tmp"), true); + Path globalTmpDir = canonPath(defaultTempDir(), true); /* They don't like trailing slashes on subpath directives */ - if (globalTmpDir.back() == '/') globalTmpDir.pop_back(); + while (!globalTmpDir.empty() && globalTmpDir.back() == '/') + globalTmpDir.pop_back(); if (getEnv("_NIX_TEST_NO_SANDBOX") != "1") { builder = "/usr/bin/sandbox-exec"; diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc index 9c25d9868..f6a3fefca 100644 --- a/src/libstore/globals.cc +++ b/src/libstore/globals.cc @@ -4,6 +4,7 @@ #include "args.hh" #include "abstract-setting-to-json.hh" #include "compute-levels.hh" +#include "file-system.hh" #include #include @@ -408,7 +409,7 @@ void initLibStore() { sshd). This breaks build users because they don't have access to the TMPDIR, in particular in ‘nix-store --serve’. */ #if __APPLE__ - if (hasPrefix(getEnv("TMPDIR").value_or("/tmp"), "/var/folders/")) + if (hasPrefix(defaultTempDir(), "/var/folders/")) unsetenv("TMPDIR"); #endif diff --git a/src/libstore/http-binary-cache-store.cc b/src/libstore/http-binary-cache-store.cc index 85c5eed4c..5da87e935 100644 --- a/src/libstore/http-binary-cache-store.cc +++ b/src/libstore/http-binary-cache-store.cc @@ -49,7 +49,7 @@ public: , BinaryCacheStore(params) , cacheUri(scheme + "://" + _cacheUri) { - if (cacheUri.back() == '/') + while (!cacheUri.empty() && cacheUri.back() == '/') cacheUri.pop_back(); diskCache = getNarInfoDiskCache(); diff --git a/src/libutil/file-system.hh b/src/libutil/file-system.hh new file mode 100644 index 000000000..1d404028b --- /dev/null +++ b/src/libutil/file-system.hh @@ -0,0 +1,17 @@ +#pragma once +/** + * @file + * + * Utiltities for working with the file sytem and file paths. + */ + +#include "types.hh" + +namespace nix { + +/** + * Return `TMPDIR`, or the default temporary directory if unset or empty. + */ +Path defaultTempDir(); + +} diff --git a/src/libutil/filesystem.cc b/src/libutil/filesystem.cc index 2a7787c0e..17c3cb8bf 100644 --- a/src/libutil/filesystem.cc +++ b/src/libutil/filesystem.cc @@ -5,15 +5,20 @@ #include "finally.hh" #include "util.hh" #include "types.hh" +#include "file-system.hh" namespace fs = std::filesystem; namespace nix { +std::string defaultTempDir() { + return getEnvNonEmpty("TMPDIR").value_or("/tmp"); +} + static Path tempName(Path tmpRoot, const Path & prefix, bool includePid, std::atomic & counter) { - tmpRoot = canonPath(tmpRoot.empty() ? getEnv("TMPDIR").value_or("/tmp") : tmpRoot, true); + tmpRoot = canonPath(tmpRoot.empty() ? defaultTempDir() : tmpRoot, true); if (includePid) return fmt("%1%/%2%-%3%-%4%", tmpRoot, prefix, getpid(), counter++); else @@ -53,7 +58,7 @@ Path createTempDir(const Path & tmpRoot, const Path & prefix, std::pair createTempFile(const Path & prefix) { - Path tmpl(getEnv("TMPDIR").value_or("/tmp") + "/" + prefix + ".XXXXXX"); + Path tmpl(defaultTempDir() + "/" + prefix + ".XXXXXX"); // Strictly speaking, this is UB, but who cares... // FIXME: use O_TMPFILE. AutoCloseFD fd(mkstemp((char *) tmpl.c_str())); diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc index e2189fc66..6c378b244 100644 --- a/src/nix-build/nix-build.cc +++ b/src/nix-build/nix-build.cc @@ -457,8 +457,9 @@ static void main_nix_build(int argc, char * * argv) // Set the environment. auto env = getEnv(); - auto tmp = getEnv("TMPDIR"); - if (!tmp) tmp = getEnv("XDG_RUNTIME_DIR").value_or("/tmp"); + auto tmp = getEnvNonEmpty("TMPDIR"); + if (!tmp) + tmp = getEnvNonEmpty("XDG_RUNTIME_DIR").value_or("/tmp"); if (pure) { decltype(env) newEnv;