aboutsummaryrefslogtreecommitdiff
path: root/src/nix/run.cc
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2016-06-02 16:51:43 +0200
committerEelco Dolstra <eelco.dolstra@logicblox.com>2016-06-02 16:51:43 +0200
commita24f2c9b8413ebc8b1776ab3f770c69e4a03007b (patch)
tree8cff7e5b4287e08ab5e93cf04063c06cdbfe3801 /src/nix/run.cc
parent6f2d51287c471238a2ff1a517c965560dfb2a149 (diff)
nix run: Mount the Nix store in a private namespace
This is a convenience command to allow users who are not privileged to create /nix/store to use Nix with regular binary caches. For example, $ NIX_REMOTE="local?state=$HOME/nix/var&real=/$HOME/nix/store" nix run firefox bashInteractive will download Firefox and bash from cache.nixos.org, then start a shell in which $HOME/nix/store is mounted on /nix/store.
Diffstat (limited to 'src/nix/run.cc')
-rw-r--r--src/nix/run.cc22
1 files changed, 21 insertions, 1 deletions
diff --git a/src/nix/run.cc b/src/nix/run.cc
index ba1efb63b..ed1c2650c 100644
--- a/src/nix/run.cc
+++ b/src/nix/run.cc
@@ -4,6 +4,11 @@
#include "shared.hh"
#include "store-api.hh"
#include "derivations.hh"
+#include "local-store.hh"
+
+#if __linux__
+#include <sys/mount.h>
+#endif
using namespace nix;
@@ -40,6 +45,20 @@ struct CmdRun : StoreCommand, MixInstallables
store->buildPaths(pathsToBuild);
+ auto store2 = store.dynamic_pointer_cast<LocalStore>();
+
+ if (store2 && store->storeDir != store2->realStoreDir) {
+#if __linux__
+ if (unshare(CLONE_NEWUSER | CLONE_NEWNS) == -1)
+ throw SysError("setting up a private mount namespace");
+
+ if (mount(store2->realStoreDir.c_str(), store->storeDir.c_str(), "", MS_BIND, 0) == -1)
+ throw SysError(format("mounting ‘%s’ on ‘%s’") % store2->realStoreDir % store->storeDir);
+#else
+ throw Error(format("mounting the Nix store on ‘%s’ is not supported on this platform") % store->storeDir);
+#endif
+ }
+
PathSet outPaths;
for (auto & path : pathsToBuild)
if (isDerivation(path)) {
@@ -55,7 +74,8 @@ struct CmdRun : StoreCommand, MixInstallables
unixPath.push_front(path + "/bin");
setenv("PATH", concatStringsSep(":", unixPath).c_str(), 1);
- execlp("bash", "bash", nullptr);
+ if (execlp("bash", "bash", nullptr) == -1)
+ throw SysError("unable to exec ‘bash’");
}
};