diff options
Diffstat (limited to 'src/libstore')
-rw-r--r-- | src/libstore/binary-cache-store.hh | 31 | ||||
-rw-r--r-- | src/libstore/build.cc | 46 | ||||
-rw-r--r-- | src/libstore/download.cc | 31 | ||||
-rw-r--r-- | src/libstore/gc.cc | 126 | ||||
-rw-r--r-- | src/libstore/legacy-ssh-store.cc | 37 | ||||
-rw-r--r-- | src/libstore/local-store.cc | 2 | ||||
-rw-r--r-- | src/libstore/local-store.hh | 8 | ||||
-rw-r--r-- | src/libstore/local.mk | 2 | ||||
-rw-r--r-- | src/libstore/machines.cc | 9 | ||||
-rw-r--r-- | src/libstore/nix-store.pc.in | 2 | ||||
-rw-r--r-- | src/libstore/parsed-derivations.cc | 4 | ||||
-rw-r--r-- | src/libstore/parsed-derivations.hh | 8 | ||||
-rw-r--r-- | src/libstore/remote-store.cc | 4 | ||||
-rw-r--r-- | src/libstore/remote-store.hh | 4 | ||||
-rw-r--r-- | src/libstore/s3-binary-cache-store.cc | 1 | ||||
-rw-r--r-- | src/libstore/ssh.cc | 3 | ||||
-rw-r--r-- | src/libstore/store-api.cc | 20 | ||||
-rw-r--r-- | src/libstore/store-api.hh | 47 |
18 files changed, 192 insertions, 193 deletions
diff --git a/src/libstore/binary-cache-store.hh b/src/libstore/binary-cache-store.hh index 6bc83fc50ca1..953f3b90af46 100644 --- a/src/libstore/binary-cache-store.hh +++ b/src/libstore/binary-cache-store.hh @@ -72,24 +72,11 @@ public: bool isValidPathUncached(const Path & path) override; - PathSet queryAllValidPaths() override - { unsupported(); } - void queryPathInfoUncached(const Path & path, Callback<std::shared_ptr<ValidPathInfo>> callback) override; - void queryReferrers(const Path & path, - PathSet & referrers) override - { unsupported(); } - - PathSet queryDerivationOutputs(const Path & path) override - { unsupported(); } - - StringSet queryDerivationOutputNames(const Path & path) override - { unsupported(); } - Path queryPathFromHashPart(const string & hashPart) override - { unsupported(); } + { unsupported("queryPathFromHashPart"); } bool wantMassQuery() override { return wantMassQuery_; } @@ -108,22 +95,10 @@ public: BuildResult buildDerivation(const Path & drvPath, const BasicDerivation & drv, BuildMode buildMode) override - { unsupported(); } + { unsupported("buildDerivation"); } void ensurePath(const Path & path) override - { unsupported(); } - - void addTempRoot(const Path & path) override - { unsupported(); } - - void addIndirectRoot(const Path & path) override - { unsupported(); } - - Roots findRoots() override - { unsupported(); } - - void collectGarbage(const GCOptions & options, GCResults & results) override - { unsupported(); } + { unsupported("ensurePath"); } ref<FSAccessor> getFSAccessor() override; diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 59abae9b90db..91eb97dfb873 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -12,6 +12,7 @@ #include "json.hh" #include "nar-info.hh" #include "parsed-derivations.hh" +#include "machines.hh" #include <algorithm> #include <iostream> @@ -802,6 +803,9 @@ private: /* Whether we're currently doing a chroot build. */ bool useChroot = false; + /* Whether we need to perform hash rewriting if there are valid output paths. */ + bool needsHashRewrite; + Path chrootRootDir; /* RAII object to delete the chroot directory. */ @@ -993,6 +997,13 @@ DerivationGoal::DerivationGoal(const Path & drvPath, const StringSet & wantedOut , wantedOutputs(wantedOutputs) , buildMode(buildMode) { +#if __linux__ + needsHashRewrite = !useChroot; +#else + /* Darwin requires hash rewriting even when sandboxing is enabled. */ + needsHashRewrite = true; +#endif + state = &DerivationGoal::getDerivation; name = (format("building of '%1%'") % drvPath).str(); trace("created"); @@ -2072,7 +2083,7 @@ void DerivationGoal::startBuilder() #endif } - else { + if (needsHashRewrite) { if (pathExists(homeDir)) throw Error(format("directory '%1%' exists; please remove it") % homeDir); @@ -2193,7 +2204,6 @@ void DerivationGoal::startBuilder() userNamespaceSync.create(); options.allowVfork = false; - options.restoreMountNamespace = false; Pid helper = startProcess([&]() { @@ -2260,7 +2270,6 @@ void DerivationGoal::startBuilder() #endif { options.allowVfork = !buildUser && !drv->isBuiltin(); - options.restoreMountNamespace = false; pid = startProcess([&]() { runChild(); }, options); @@ -2415,7 +2424,7 @@ void DerivationGoal::writeStructuredAttrs() objects consisting entirely of those values. (So nested arrays or objects are not supported.) */ - auto handleSimpleType = [](const nlohmann::json & value) -> std::experimental::optional<std::string> { + auto handleSimpleType = [](const nlohmann::json & value) -> std::optional<std::string> { if (value.is_string()) return shellEscape(value); @@ -2501,17 +2510,17 @@ void setupSeccomp() seccomp_release(ctx); }); - if (settings.thisSystem == "x86_64-linux" && + if (nativeSystem == "x86_64-linux" && seccomp_arch_add(ctx, SCMP_ARCH_X86) != 0) throw SysError("unable to add 32-bit seccomp architecture"); - if (settings.thisSystem == "x86_64-linux" && + if (nativeSystem == "x86_64-linux" && seccomp_arch_add(ctx, SCMP_ARCH_X32) != 0) throw SysError("unable to add X32 seccomp architecture"); - if (settings.thisSystem == "aarch64-linux" && + if (nativeSystem == "aarch64-linux" && seccomp_arch_add(ctx, SCMP_ARCH_ARM) != 0) - printError("unsable to add ARM seccomp architecture; this may result in spurious build failures if running 32-bit ARM processes."); + printError("unable to add ARM seccomp architecture; this may result in spurious build failures if running 32-bit ARM processes"); /* Prevent builders from creating setuid/setgid binaries. */ for (int perm : { S_ISUID, S_ISGID }) { @@ -2874,6 +2883,10 @@ void DerivationGoal::runChild() for (auto & i : missingPaths) { sandboxProfile += (format("\t(subpath \"%1%\")\n") % i.c_str()).str(); } + /* Also add redirected outputs to the chroot */ + for (auto & i : redirectedOutputs) { + sandboxProfile += (format("\t(subpath \"%1%\")\n") % i.second.c_str()).str(); + } sandboxProfile += ")\n"; /* Our inputs (transitive dependencies and any impurities computed above) @@ -3052,7 +3065,9 @@ void DerivationGoal::registerOutputs() throw SysError(format("moving build output '%1%' from the sandbox to the Nix store") % path); } if (buildMode != bmCheck) actualPath = worker.store.toRealPath(path); - } else { + } + + if (needsHashRewrite) { Path redirected = redirectedOutputs[path]; if (buildMode == bmRepair && redirectedBadOutputs.find(path) != redirectedBadOutputs.end() @@ -3313,8 +3328,8 @@ void DerivationGoal::checkOutputs(const std::map<Path, ValidPathInfo> & outputs) struct Checks { bool ignoreSelfRefs = false; - std::experimental::optional<uint64_t> maxSize, maxClosureSize; - std::experimental::optional<Strings> allowedReferences, allowedRequisites, disallowedReferences, disallowedRequisites; + std::optional<uint64_t> maxSize, maxClosureSize; + std::optional<Strings> allowedReferences, allowedRequisites, disallowedReferences, disallowedRequisites; }; /* Compute the closure and closure size of some output. This @@ -3361,7 +3376,7 @@ void DerivationGoal::checkOutputs(const std::map<Path, ValidPathInfo> & outputs) info.path, closureSize, *checks.maxClosureSize); } - auto checkRefs = [&](const std::experimental::optional<Strings> & value, bool allowed, bool recursive) + auto checkRefs = [&](const std::optional<Strings> & value, bool allowed, bool recursive) { if (!value) return; @@ -3415,7 +3430,7 @@ void DerivationGoal::checkOutputs(const std::map<Path, ValidPathInfo> & outputs) if (maxClosureSize != output->end()) checks.maxClosureSize = maxClosureSize->get<uint64_t>(); - auto get = [&](const std::string & name) -> std::experimental::optional<Strings> { + auto get = [&](const std::string & name) -> std::optional<Strings> { auto i = output->find(name); if (i != output->end()) { Strings res; @@ -4413,6 +4428,11 @@ static void primeCache(Store & store, const PathSet & paths) PathSet willBuild, willSubstitute, unknown; unsigned long long downloadSize, narSize; store.queryMissing(paths, willBuild, willSubstitute, unknown, downloadSize, narSize); + + if (!willBuild.empty() && 0 == settings.maxBuildJobs && getMachines().empty()) + throw Error( + "%d derivations need to be built, but neither local builds ('--max-jobs') " + "nor remote builds ('--builders') are enabled", willBuild.size()); } diff --git a/src/libstore/download.cc b/src/libstore/download.cc index 467f570bbf05..22382ab1d6e8 100644 --- a/src/libstore/download.cc +++ b/src/libstore/download.cc @@ -614,6 +614,22 @@ struct CurlDownloader : public Downloader writeFull(wakeupPipe.writeSide.get(), " "); } +#ifdef ENABLE_S3 + std::tuple<std::string, std::string, Store::Params> parseS3Uri(std::string uri) + { + auto [path, params] = splitUriAndParams(uri); + + auto slash = path.find('/', 5); // 5 is the length of "s3://" prefix + if (slash == std::string::npos) + throw nix::Error("bad S3 URI '%s'", path); + + std::string bucketName(path, 5, slash - 5); + std::string key(path, slash + 1); + + return {bucketName, key, params}; + } +#endif + void enqueueDownload(const DownloadRequest & request, Callback<DownloadResult> callback) override { @@ -622,12 +638,15 @@ struct CurlDownloader : public Downloader // FIXME: do this on a worker thread try { #ifdef ENABLE_S3 - S3Helper s3Helper("", Aws::Region::US_EAST_1, "", ""); // FIXME: make configurable - auto slash = request.uri.find('/', 5); - if (slash == std::string::npos) - throw nix::Error("bad S3 URI '%s'", request.uri); - std::string bucketName(request.uri, 5, slash - 5); - std::string key(request.uri, slash + 1); + auto [bucketName, key, params] = parseS3Uri(request.uri); + + std::string profile = get(params, "profile", ""); + std::string region = get(params, "region", Aws::Region::US_EAST_1); + std::string scheme = get(params, "scheme", ""); + std::string endpoint = get(params, "endpoint", ""); + + S3Helper s3Helper(profile, region, scheme, endpoint); + // FIXME: implement ETag auto s3Res = s3Helper.getObject(bucketName, key); DownloadResult res; diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index b415d5421476..26e2b0dca7ca 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -129,8 +129,8 @@ Path LocalFSStore::addPermRoot(const Path & _storePath, check if the root is in a directory in or linked from the gcroots directory. */ if (settings.checkRootReachability) { - Roots roots = findRoots(); - if (roots.find(gcRoot) == roots.end()) + Roots roots = findRoots(false); + if (roots[storePath].count(gcRoot) == 0) printError( format( "warning: '%1%' is not in a directory where the garbage collector looks for roots; " @@ -197,10 +197,11 @@ void LocalStore::addTempRoot(const Path & path) } -std::set<std::pair<pid_t, Path>> LocalStore::readTempRoots(FDs & fds) -{ - std::set<std::pair<pid_t, Path>> tempRoots; +static std::string censored = "{censored}"; + +void LocalStore::findTempRoots(FDs & fds, Roots & tempRoots, bool censor) +{ /* Read the `temproots' directory for per-process temporary root files. */ for (auto & i : readDirectory(tempRootsDir)) { @@ -250,14 +251,12 @@ std::set<std::pair<pid_t, Path>> LocalStore::readTempRoots(FDs & fds) Path root(contents, pos, end - pos); debug("got temporary root '%s'", root); assertStorePath(root); - tempRoots.emplace(pid, root); + tempRoots[root].emplace(censor ? censored : fmt("{temp:%d}", pid)); pos = end + 1; } fds.push_back(fd); /* keep open */ } - - return tempRoots; } @@ -266,7 +265,7 @@ void LocalStore::findRoots(const Path & path, unsigned char type, Roots & roots) auto foundRoot = [&](const Path & path, const Path & target) { Path storePath = toStorePath(target); if (isStorePath(storePath) && isValidPath(storePath)) - roots[path] = storePath; + roots[storePath].emplace(path); else printInfo(format("skipping invalid root from '%1%' to '%2%'") % path % storePath); }; @@ -306,7 +305,7 @@ void LocalStore::findRoots(const Path & path, unsigned char type, Roots & roots) else if (type == DT_REG) { Path storePath = storeDir + "/" + baseNameOf(path); if (isStorePath(storePath) && isValidPath(storePath)) - roots[path] = storePath; + roots[storePath].emplace(path); } } @@ -321,44 +320,31 @@ void LocalStore::findRoots(const Path & path, unsigned char type, Roots & roots) } -Roots LocalStore::findRootsNoTemp() +void LocalStore::findRootsNoTemp(Roots & roots, bool censor) { - Roots roots; - /* Process direct roots in {gcroots,profiles}. */ findRoots(stateDir + "/" + gcRootsDir, DT_UNKNOWN, roots); findRoots(stateDir + "/profiles", DT_UNKNOWN, roots); - /* Add additional roots returned by the program specified by the - NIX_ROOT_FINDER environment variable. This is typically used - to add running programs to the set of roots (to prevent them - from being garbage collected). */ - size_t n = 0; - for (auto & root : findRuntimeRoots()) - roots[fmt("{memory:%d}", n++)] = root; - - return roots; + /* Add additional roots returned by different platforms-specific + heuristics. This is typically used to add running programs to + the set of roots (to prevent them from being garbage collected). */ + findRuntimeRoots(roots, censor); } -Roots LocalStore::findRoots() +Roots LocalStore::findRoots(bool censor) { - Roots roots = findRootsNoTemp(); + Roots roots; + findRootsNoTemp(roots, censor); FDs fds; - pid_t prev = -1; - size_t n = 0; - for (auto & root : readTempRoots(fds)) { - if (prev != root.first) n = 0; - prev = root.first; - roots[fmt("{temp:%d:%d}", root.first, n++)] = root.second; - } + findTempRoots(fds, roots, censor); return roots; } - -static void readProcLink(const string & file, StringSet & paths) +static void readProcLink(const string & file, Roots & roots) { /* 64 is the starting buffer size gnu readlink uses... */ auto bufsiz = ssize_t{64}; @@ -377,8 +363,8 @@ try_again: goto try_again; } if (res > 0 && buf[0] == '/') - paths.emplace(static_cast<char *>(buf), res); - return; + roots[std::string(static_cast<char *>(buf), res)] + .emplace(file); } static string quoteRegexChars(const string & raw) @@ -387,20 +373,20 @@ static string quoteRegexChars(const string & raw) return std::regex_replace(raw, specialRegex, R"(\$&)"); } -static void readFileRoots(const char * path, StringSet & paths) +static void readFileRoots(const char * path, Roots & roots) { try { - paths.emplace(readFile(path)); + roots[readFile(path)].emplace(path); } catch (SysError & e) { if (e.errNo != ENOENT && e.errNo != EACCES) throw; } } -PathSet LocalStore::findRuntimeRoots() +void LocalStore::findRuntimeRoots(Roots & roots, bool censor) { - PathSet roots; - StringSet paths; + Roots unchecked; + auto procDir = AutoCloseDir{opendir("/proc")}; if (procDir) { struct dirent * ent; @@ -410,10 +396,10 @@ PathSet LocalStore::findRuntimeRoots() while (errno = 0, ent = readdir(procDir.get())) { checkInterrupt(); if (std::regex_match(ent->d_name, digitsRegex)) { - readProcLink((format("/proc/%1%/exe") % ent->d_name).str(), paths); - readProcLink((format("/proc/%1%/cwd") % ent->d_name).str(), paths); + readProcLink(fmt("/proc/%s/exe" ,ent->d_name), unchecked); + readProcLink(fmt("/proc/%s/cwd", ent->d_name), unchecked); - auto fdStr = (format("/proc/%1%/fd") % ent->d_name).str(); + auto fdStr = fmt("/proc/%s/fd", ent->d_name); auto fdDir = AutoCloseDir(opendir(fdStr.c_str())); if (!fdDir) { if (errno == ENOENT || errno == EACCES) @@ -422,9 +408,8 @@ PathSet LocalStore::findRuntimeRoots() } struct dirent * fd_ent; while (errno = 0, fd_ent = readdir(fdDir.get())) { - if (fd_ent->d_name[0] != '.') { - readProcLink((format("%1%/%2%") % fdStr % fd_ent->d_name).str(), paths); - } + if (fd_ent->d_name[0] != '.') + readProcLink(fmt("%s/%s", fdStr, fd_ent->d_name), unchecked); } if (errno) { if (errno == ESRCH) @@ -434,18 +419,19 @@ PathSet LocalStore::findRuntimeRoots() fdDir.reset(); try { - auto mapLines = - tokenizeString<std::vector<string>>(readFile((format("/proc/%1%/maps") % ent->d_name).str(), true), "\n"); - for (const auto& line : mapLines) { + auto mapFile = fmt("/proc/%s/maps", ent->d_name); + auto mapLines = tokenizeString<std::vector<string>>(readFile(mapFile, true), "\n"); + for (const auto & line : mapLines) { auto match = std::smatch{}; if (std::regex_match(line, match, mapRegex)) - paths.emplace(match[1]); + unchecked[match[1]].emplace(mapFile); } - auto envString = readFile((format("/proc/%1%/environ") % ent->d_name).str(), true); + auto envFile = fmt("/proc/%s/environ", ent->d_name); + auto envString = readFile(envFile, true); auto env_end = std::sregex_iterator{}; for (auto i = std::sregex_iterator{envString.begin(), envString.end(), storePathRegex}; i != env_end; ++i) - paths.emplace(i->str()); + unchecked[i->str()].emplace(envFile); } catch (SysError & e) { if (errno == ENOENT || errno == EACCES || errno == ESRCH) continue; @@ -465,7 +451,7 @@ PathSet LocalStore::findRuntimeRoots() for (const auto & line : lsofLines) { std::smatch match; if (std::regex_match(line, match, lsofRegex)) - paths.emplace(match[1]); + unchecked[match[1]].emplace("{lsof}"); } } catch (ExecError & e) { /* lsof not installed, lsof failed */ @@ -473,21 +459,23 @@ PathSet LocalStore::findRuntimeRoots() #endif #if defined(__linux__) - readFileRoots("/proc/sys/kernel/modprobe", paths); - readFileRoots("/proc/sys/kernel/fbsplash", paths); - readFileRoots("/proc/sys/kernel/poweroff_cmd", paths); + readFileRoots("/proc/sys/kernel/modprobe", unchecked); + readFileRoots("/proc/sys/kernel/fbsplash", unchecked); + readFileRoots("/proc/sys/kernel/poweroff_cmd", unchecked); #endif - for (auto & i : paths) - if (isInStore(i)) { - Path path = toStorePath(i); - if (roots.find(path) == roots.end() && isStorePath(path) && isValidPath(path)) { + for (auto & [target, links] : unchecked) { + if (isInStore(target)) { + Path path = toStorePath(target); + if (isStorePath(path) && isValidPath(path)) { debug(format("got additional root '%1%'") % path); - roots.insert(path); + if (censor) + roots[path].insert(censored); + else + roots[path].insert(links.begin(), links.end()); } } - - return roots; + } } @@ -754,16 +742,20 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) /* Find the roots. Since we've grabbed the GC lock, the set of permanent roots cannot increase now. */ printError(format("finding garbage collector roots...")); - Roots rootMap = options.ignoreLiveness ? Roots() : findRootsNoTemp(); + Roots rootMap; + if (!options.ignoreLiveness) + findRootsNoTemp(rootMap, true); - for (auto & i : rootMap) state.roots.insert(i.second); + for (auto & i : rootMap) state.roots.insert(i.first); /* Read the temporary roots. This acquires read locks on all per-process temporary root files. So after this point no paths can be added to the set of temporary roots. */ FDs fds; - for (auto & root : readTempRoots(fds)) - state.tempRoots.insert(root.second); + Roots tempRoots; + findTempRoots(fds, tempRoots, true); + for (auto & root : tempRoots) + state.tempRoots.insert(root.first); state.roots.insert(state.tempRoots.begin(), state.tempRoots.end()); /* After this point the set of roots or temporary roots cannot diff --git a/src/libstore/legacy-ssh-store.cc b/src/libstore/legacy-ssh-store.cc index 26e1851981db..7c9bc2b68ba8 100644 --- a/src/libstore/legacy-ssh-store.cc +++ b/src/libstore/legacy-ssh-store.cc @@ -187,28 +187,17 @@ struct LegacySSHStore : public Store copyNAR(conn->from, sink); } - PathSet queryAllValidPaths() override { unsupported(); } - - void queryReferrers(const Path & path, PathSet & referrers) override - { unsupported(); } - - PathSet queryDerivationOutputs(const Path & path) override - { unsupported(); } - - StringSet queryDerivationOutputNames(const Path & path) override - { unsupported(); } - Path queryPathFromHashPart(const string & hashPart) override - { unsupported(); } + { unsupported("queryPathFromHashPart"); } Path addToStore(const string & name, const Path & srcPath, bool recursive, HashType hashAlgo, PathFilter & filter, RepairFlag repair) override - { unsupported(); } + { unsupported("addToStore"); } Path addTextToStore(const string & name, const string & s, const PathSet & references, RepairFlag repair) override - { unsupported(); } + { unsupported("addTextToStore"); } BuildResult buildDerivation(const Path & drvPath, const BasicDerivation & drv, BuildMode buildMode) override @@ -242,25 +231,7 @@ struct LegacySSHStore : public Store } void ensurePath(const Path & path) override - { unsupported(); } - - void addTempRoot(const Path & path) override - { unsupported(); } - - void addIndirectRoot(const Path & path) override - { unsupported(); } - - Roots findRoots() override - { unsupported(); } - - void collectGarbage(const GCOptions & options, GCResults & results) override - { unsupported(); } - - ref<FSAccessor> getFSAccessor() override - { unsupported(); } - - void addSignatures(const Path & storePath, const StringSet & sigs) override - { unsupported(); } + { unsupported("ensurePath"); } void computeFSClosure(const PathSet & paths, PathSet & out, bool flipDirection = false, diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 5b4e7ca4ca99..485fdd691932 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -366,8 +366,6 @@ void LocalStore::makeStoreWritable() throw SysError("getting info about the Nix store mount point"); if (stat.f_flag & ST_RDONLY) { - saveMountNamespace(); - if (unshare(CLONE_NEWNS) == -1) throw SysError("setting up a private mount namespace"); diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index fce963433a5e..6b655647b031 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -180,11 +180,11 @@ private: typedef std::shared_ptr<AutoCloseFD> FDPtr; typedef list<FDPtr> FDs; - std::set<std::pair<pid_t, Path>> readTempRoots(FDs & fds); + void findTempRoots(FDs & fds, Roots & roots, bool censor); public: - Roots findRoots() override; + Roots findRoots(bool censor) override; void collectGarbage(const GCOptions & options, GCResults & results) override; @@ -267,9 +267,9 @@ private: void findRoots(const Path & path, unsigned char type, Roots & roots); - Roots findRootsNoTemp(); + void findRootsNoTemp(Roots & roots, bool censor); - PathSet findRuntimeRoots(); + void findRuntimeRoots(Roots & roots, bool censor); void removeUnusedLinks(const GCState & state); diff --git a/src/libstore/local.mk b/src/libstore/local.mk index 3799257f83ff..89fc918c30fd 100644 --- a/src/libstore/local.mk +++ b/src/libstore/local.mk @@ -6,7 +6,7 @@ libstore_DIR := $(d) libstore_SOURCES := $(wildcard $(d)/*.cc $(d)/builtins/*.cc) -libstore_LIBS = libutil libformat +libstore_LIBS = libutil libstore_LDFLAGS = $(SQLITE3_LIBS) -lbz2 $(LIBCURL_LIBS) $(SODIUM_LIBS) -pthread ifneq ($(OS), FreeBSD) diff --git a/src/libstore/machines.cc b/src/libstore/machines.cc index edd03d147832..f848582dafd4 100644 --- a/src/libstore/machines.cc +++ b/src/libstore/machines.cc @@ -89,10 +89,11 @@ void parseMachines(const std::string & s, Machines & machines) Machines getMachines() { - Machines machines; - - parseMachines(settings.builders, machines); - + static auto machines = [&]() { + Machines machines; + parseMachines(settings.builders, machines); + return machines; + }(); return machines; } diff --git a/src/libstore/nix-store.pc.in b/src/libstore/nix-store.pc.in index 5cf22faadcbe..6d67b1e03808 100644 --- a/src/libstore/nix-store.pc.in +++ b/src/libstore/nix-store.pc.in @@ -6,4 +6,4 @@ Name: Nix Description: Nix Package Manager Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lnixstore -lnixutil -Cflags: -I${includedir}/nix -std=c++14 +Cflags: -I${includedir}/nix -std=c++17 diff --git a/src/libstore/parsed-derivations.cc b/src/libstore/parsed-derivations.cc index dc3286482736..17fde00a0167 100644 --- a/src/libstore/parsed-derivations.cc +++ b/src/libstore/parsed-derivations.cc @@ -16,7 +16,7 @@ ParsedDerivation::ParsedDerivation(const Path & drvPath, BasicDerivation & drv) } } -std::experimental::optional<std::string> ParsedDerivation::getStringAttr(const std::string & name) const +std::optional<std::string> ParsedDerivation::getStringAttr(const std::string & name) const { if (structuredAttrs) { auto i = structuredAttrs->find(name); @@ -56,7 +56,7 @@ bool ParsedDerivation::getBoolAttr(const std::string & name, bool def) const } } -std::experimental::optional<Strings> ParsedDerivation::getStringsAttr(const std::string & name) const +std::optional<Strings> ParsedDerivation::getStringsAttr(const std::string & name) const { if (structuredAttrs) { auto i = structuredAttrs->find(name); diff --git a/src/libstore/parsed-derivations.hh b/src/libstore/parsed-derivations.hh index 0a82c146172b..ed07dc652e8d 100644 --- a/src/libstore/parsed-derivations.hh +++ b/src/libstore/parsed-derivations.hh @@ -8,22 +8,22 @@ class ParsedDerivation { Path drvPath; BasicDerivation & drv; - std::experimental::optional<nlohmann::json> structuredAttrs; + std::optional<nlohmann::json> structuredAttrs; public: ParsedDerivation(const Path & drvPath, BasicDerivation & drv); - const std::experimental::optional<nlohmann::json> & getStructuredAttrs() const + const std::optional<nlohmann::json> & getStructuredAttrs() const { return structuredAttrs; } - std::experimental::optional<std::string> getStringAttr(const std::string & name) const; + std::optional<std::string> getStringAttr(const std::string & name) const; bool getBoolAttr(const std::string & name, bool def = false) const; - std::experimental::optional<Strings> getStringsAttr(const std::string & name) const; + std::optional<Strings> getStringsAttr(const std::string & name) const; StringSet getRequiredSystemFeatures() const; diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index def140cfbe18..15faf78a526d 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -596,7 +596,7 @@ void RemoteStore::syncWithGC() } -Roots RemoteStore::findRoots() +Roots RemoteStore::findRoots(bool censor) { auto conn(getConnection()); conn->to << wopFindRoots; @@ -606,7 +606,7 @@ Roots RemoteStore::findRoots() while (count--) { Path link = readString(conn->from); Path target = readStorePath(*this, conn->from); - result[link] = target; + result[target].emplace(link); } return result; } diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh index 4f554b5980e8..80f18ab715d9 100644 --- a/src/libstore/remote-store.hh +++ b/src/libstore/remote-store.hh @@ -82,7 +82,7 @@ public: void syncWithGC() override; - Roots findRoots() override; + Roots findRoots(bool censor) override; void collectGarbage(const GCOptions & options, GCResults & results) override; @@ -149,7 +149,7 @@ public: private: ref<RemoteStore::Connection> openConnection() override; - std::experimental::optional<std::string> path; + std::optional<std::string> path; }; diff --git a/src/libstore/s3-binary-cache-store.cc b/src/libstore/s3-binary-cache-store.cc index 51de89e0d92f..cd547a964850 100644 --- a/src/libstore/s3-binary-cache-store.cc +++ b/src/libstore/s3-binary-cache-store.cc @@ -126,6 +126,7 @@ ref<Aws::Client::ClientConfiguration> S3Helper::makeConfig(const string & region res->endpointOverride = endpoint; } res->requestTimeoutMs = 600 * 1000; + res->connectTimeoutMs = 5 * 1000; res->retryStrategy = std::make_shared<RetryStrategy>(); res->caFile = settings.caFile; return res; diff --git a/src/libstore/ssh.cc b/src/libstore/ssh.cc index cf133b57cb20..5e0e44935cca 100644 --- a/src/libstore/ssh.cc +++ b/src/libstore/ssh.cc @@ -1,5 +1,4 @@ #include "ssh.hh" -#include "affinity.hh" namespace nix { @@ -35,9 +34,7 @@ std::unique_ptr<SSHMaster::Connection> SSHMaster::startCommand(const std::string auto conn = std::make_unique<Connection>(); conn->sshPid = startProcess([&]() { - restoreAffinity(); restoreSignals(); - restoreMountNamespace(); close(in.writeSide.get()); close(out.readSide.get()); diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index dc54c735fdb1..c13ff11564ec 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -562,10 +562,10 @@ void Store::buildPaths(const PathSet & paths, BuildMode buildMode) { for (auto & path : paths) if (isDerivation(path)) - unsupported(); + unsupported("buildPaths"); if (queryValidPaths(paths).size() != paths.size()) - unsupported(); + unsupported("buildPaths"); } @@ -842,12 +842,11 @@ namespace nix { RegisterStoreImplementation::Implementations * RegisterStoreImplementation::implementations = 0; - -ref<Store> openStore(const std::string & uri_, - const Store::Params & extraParams) +/* Split URI into protocol+hierarchy part and its parameter set. */ +std::pair<std::string, Store::Params> splitUriAndParams(const std::string & uri_) { auto uri(uri_); - Store::Params params(extraParams); + Store::Params params; auto q = uri.find('?'); if (q != std::string::npos) { for (auto s : tokenizeString<Strings>(uri.substr(q + 1), "&")) { @@ -873,6 +872,15 @@ ref<Store> openStore(const std::string & uri_, } uri = uri_.substr(0, q); } + return {uri, params}; +} + +ref<Store> openStore(const std::string & uri_, + const Store::Params & extraParams) +{ + auto [uri, uriParams] = splitUriAndParams(uri_); + auto params = extraParams; + params.insert(uriParams.begin(), uriParams.end()); for (auto fun : *RegisterStoreImplementation::implementations) { auto store = fun(uri, params); diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index 106b2be5e6b2..7a1b31d0ff59 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -11,6 +11,8 @@ #include <atomic> #include <limits> #include <map> +#include <unordered_map> +#include <unordered_set> #include <memory> #include <string> @@ -47,7 +49,7 @@ const size_t storePathHashLen = 32; // i.e. 160 bits const uint32_t exportMagic = 0x4558494e; -typedef std::map<Path, Path> Roots; +typedef std::unordered_map<Path, std::unordered_set<std::string>> Roots; struct GCOptions @@ -349,7 +351,8 @@ public: (i.e. you'll get /nix/store/<hash> rather than /nix/store/<hash>-<name>). Use queryPathInfo() to obtain the full store path. */ - virtual PathSet queryAllValidPaths() = 0; + virtual PathSet queryAllValidPaths() + { unsupported("queryAllValidPaths"); } /* Query information about a valid path. It is permitted to omit the name part of the store path. */ @@ -368,8 +371,8 @@ public: /* Queries the set of incoming FS references for a store path. The result is not cleared. */ - virtual void queryReferrers(const Path & path, - PathSet & referrers) = 0; + virtual void queryReferrers(const Path & path, PathSet & referrers) + { unsupported("queryReferrers"); } /* Return all currently valid derivations that have `path' as an output. (Note that the result of `queryDeriver()' is the @@ -378,10 +381,12 @@ public: virtual PathSet queryValidDerivers(const Path & path) { return {}; }; /* Query the outputs of the derivation denoted by `path'. */ - virtual PathSet queryDerivationOutputs(const Path & path) = 0; + virtual PathSet queryDerivationOutputs(const Path & path) + { unsupported("queryDerivationOutputs"); } /* Query the output names of the derivation denoted by `path'. */ - virtual StringSet queryDerivationOutputNames(const Path & path) = 0; + virtual StringSet queryDerivationOutputNames(const Path & path) + { unsupported("queryDerivationOutputNames"); } /* Query the full store path given the hash part of a valid store path, or "" if the path doesn't exist. */ @@ -447,14 +452,16 @@ public: /* Add a store path as a temporary root of the garbage collector. The root disappears as soon as we exit. */ - virtual void addTempRoot(const Path & path) = 0; + virtual void addTempRoot(const Path & path) + { unsupported("addTempRoot"); } /* Add an indirect root, which is merely a symlink to `path' from /nix/var/nix/gcroots/auto/<hash of `path'>. `path' is supposed to be a symlink to a store path. The garbage collector will automatically remove the indirect root when it finds that `path' has disappeared. */ - virtual void addIndirectRoot(const Path & path) = 0; + virtual void addIndirectRoot(const Path & path) + { unsupported("addIndirectRoot"); } /* Acquire the global GC lock, then immediately release it. This function must be called after registering a new permanent root, @@ -478,11 +485,15 @@ public: /* Find the roots of the garbage collector. Each root is a pair (link, storepath) where `link' is the path of the symlink - outside of the Nix store that point to `storePath'. */ - virtual Roots findRoots() = 0; + outside of the Nix store that point to `storePath'. If + 'censor' is true, privacy-sensitive information about roots + found in /proc is censored. */ + virtual Roots findRoots(bool censor) + { unsupported("findRoots"); } /* Perform a garbage collection. */ - virtual void collectGarbage(const GCOptions & options, GCResults & results) = 0; + virtual void collectGarbage(const GCOptions & options, GCResults & results) + { unsupported("collectGarbage"); } /* Return a string representing information about the path that can be loaded into the database using `nix-store --load-db' or @@ -513,11 +524,13 @@ public: virtual bool verifyStore(bool checkContents, RepairFlag repair = NoRepair) { return false; }; /* Return an object to access files in the Nix store. */ - virtual ref<FSAccessor> getFSAccessor() = 0; + virtual ref<FSAccessor> getFSAccessor() + { unsupported("getFSAccessor"); } /* Add signatures to the specified store path. The signatures are not verified. */ - virtual void addSignatures(const Path & storePath, const StringSet & sigs) = 0; + virtual void addSignatures(const Path & storePath, const StringSet & sigs) + { unsupported("addSignatures"); } /* Utility functions. */ @@ -620,9 +633,9 @@ protected: Stats stats; /* Unsupported methods. */ - [[noreturn]] void unsupported() + [[noreturn]] void unsupported(const std::string & op) { - throw Unsupported("requested operation is not supported by store '%s'", getUri()); + throw Unsupported("operation '%s' is not supported by store '%s'", op, getUri()); } }; @@ -789,4 +802,8 @@ ValidPathInfo decodeValidPathInfo(std::istream & str, for paths created by makeFixedOutputPath() / addToStore(). */ std::string makeFixedOutputCA(bool recursive, const Hash & hash); + +/* Split URI into protocol+hierarchy part and its parameter set. */ +std::pair<std::string, Store::Params> splitUriAndParams(const std::string & uri); + } |