From 18b7363a699c0b5a4bf59d2b320dfc2b84dc4e67 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 31 Oct 2016 17:09:52 +0100 Subject: Support optional sandbox paths For example, you can now set build-sandbox-paths = /dev/nvidiactl? to specify that /dev/nvidiactl should only be mounted in the sandbox if it exists in the host filesystem. This is useful e.g. for EC2 images that should support both CUDA and non-CUDA instances. --- src/libstore/build.cc | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) (limited to 'src/libstore/build.cc') diff --git a/src/libstore/build.cc b/src/libstore/build.cc index efd6c07190db..b682a80195fb 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -768,7 +768,14 @@ private: GoalState state; /* Stuff we need to pass to initChild(). */ - typedef map DirsInChroot; // maps target path to source path + struct ChrootPath { + Path source; + bool optional; + ChrootPath(Path source = "", bool optional = false) + : source(source), optional(optional) + { } + }; + typedef map DirsInChroot; // maps target path to source path DirsInChroot dirsInChroot; typedef map Environment; Environment env; @@ -1865,12 +1872,18 @@ void DerivationGoal::startBuilder() dirsInChroot.clear(); - for (auto & i : dirs) { + for (auto i : dirs) { + if (i.empty()) continue; + bool optional = false; + if (i[i.size() - 1] == '?') { + optional = true; + i.pop_back(); + } size_t p = i.find('='); if (p == string::npos) - dirsInChroot[i] = i; + dirsInChroot[i] = {i, optional}; else - dirsInChroot[string(i, 0, p)] = string(i, p + 1); + dirsInChroot[string(i, 0, p)] = {string(i, p + 1), optional}; } dirsInChroot[tmpDirInSandbox] = tmpDir; @@ -1878,8 +1891,8 @@ void DerivationGoal::startBuilder() PathSet closure; for (auto & i : dirsInChroot) try { - if (worker.store.isInStore(i.second)) - worker.store.computeFSClosure(worker.store.toStorePath(i.second), closure); + if (worker.store.isInStore(i.second.source)) + worker.store.computeFSClosure(worker.store.toStorePath(i.second.source), closure); } catch (Error & e) { throw Error(format("while processing ‘build-sandbox-paths’: %s") % e.what()); } @@ -2325,12 +2338,16 @@ void DerivationGoal::runChild() environment. */ for (auto & i : dirsInChroot) { struct stat st; - Path source = i.second; + Path source = i.second.source; Path target = chrootRootDir + i.first; if (source == "/proc") continue; // backwards compatibility debug(format("bind mounting ‘%1%’ to ‘%2%’") % source % target); - if (stat(source.c_str(), &st) == -1) - throw SysError(format("getting attributes of path ‘%1%’") % source); + if (stat(source.c_str(), &st) == -1) { + if (i.second.optional && errno == ENOENT) + continue; + else + throw SysError(format("getting attributes of path ‘%1%’") % source); + } if (S_ISDIR(st.st_mode)) createDirs(target); else { -- cgit 1.4.1