From a24f2c9b8413ebc8b1776ab3f770c69e4a03007b Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 2 Jun 2016 16:51:43 +0200 Subject: [PATCH] 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. --- src/libstore/local-store.hh | 4 ++++ src/nix/run.cc | 22 +++++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index 3a2568ec9..0c2766f66 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -73,6 +73,8 @@ private: Sync _state; +public: + const Path realStoreDir; const Path dbDir; const Path linksDir; @@ -80,6 +82,8 @@ private: const Path schemaPath; const Path trashDir; +private: + bool requireSigs; PublicKeys publicKeys; 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 +#endif using namespace nix; @@ -40,6 +45,20 @@ struct CmdRun : StoreCommand, MixInstallables store->buildPaths(pathsToBuild); + auto store2 = store.dynamic_pointer_cast(); + + 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’"); } };