aboutsummaryrefslogtreecommitdiff
path: root/src/nix/run.cc
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2021-07-27 14:23:24 +0200
committerEelco Dolstra <edolstra@gmail.com>2021-07-27 14:24:03 +0200
commited5ad59dc16d8207f14c23f7fca903ee408eb54e (patch)
treef306c29b27760194717677327a547a6f9dcc3334 /src/nix/run.cc
parentc000cec27fcb16548606830410be265eb082f777 (diff)
nix develop: Support chroot stores
Fixes #5024.
Diffstat (limited to 'src/nix/run.cc')
-rw-r--r--src/nix/run.cc63
1 files changed, 31 insertions, 32 deletions
diff --git a/src/nix/run.cc b/src/nix/run.cc
index 0c8afec2d..7597b61f7 100644
--- a/src/nix/run.cc
+++ b/src/nix/run.cc
@@ -1,3 +1,4 @@
+#include "run.hh"
#include "command.hh"
#include "common-args.hh"
#include "shared.hh"
@@ -20,45 +21,43 @@ using namespace nix;
std::string chrootHelperName = "__run_in_chroot";
-struct RunCommon : virtual Command
-{
+namespace nix {
- using Command::run;
+void runProgramInStore(ref<Store> store,
+ const std::string & program,
+ const Strings & args)
+{
+ stopProgressBar();
- void runProgram(ref<Store> store,
- const std::string & program,
- const Strings & args)
- {
- stopProgressBar();
+ restoreProcessContext();
- restoreProcessContext();
+ /* If this is a diverted store (i.e. its "logical" location
+ (typically /nix/store) differs from its "physical" location
+ (e.g. /home/eelco/nix/store), then run the command in a
+ chroot. For non-root users, this requires running it in new
+ mount and user namespaces. Unfortunately,
+ unshare(CLONE_NEWUSER) doesn't work in a multithreaded program
+ (which "nix" is), so we exec() a single-threaded helper program
+ (chrootHelper() below) to do the work. */
+ auto store2 = store.dynamic_pointer_cast<LocalStore>();
- /* If this is a diverted store (i.e. its "logical" location
- (typically /nix/store) differs from its "physical" location
- (e.g. /home/eelco/nix/store), then run the command in a
- chroot. For non-root users, this requires running it in new
- mount and user namespaces. Unfortunately,
- unshare(CLONE_NEWUSER) doesn't work in a multithreaded
- program (which "nix" is), so we exec() a single-threaded
- helper program (chrootHelper() below) to do the work. */
- auto store2 = store.dynamic_pointer_cast<LocalStore>();
+ if (store2 && store->storeDir != store2->getRealStoreDir()) {
+ Strings helperArgs = { chrootHelperName, store->storeDir, store2->getRealStoreDir(), program };
+ for (auto & arg : args) helperArgs.push_back(arg);
- if (store2 && store->storeDir != store2->getRealStoreDir()) {
- Strings helperArgs = { chrootHelperName, store->storeDir, store2->getRealStoreDir(), program };
- for (auto & arg : args) helperArgs.push_back(arg);
+ execv(readLink("/proc/self/exe").c_str(), stringsToCharPtrs(helperArgs).data());
- execv(readLink("/proc/self/exe").c_str(), stringsToCharPtrs(helperArgs).data());
+ throw SysError("could not execute chroot helper");
+ }
- throw SysError("could not execute chroot helper");
- }
+ execvp(program.c_str(), stringsToCharPtrs(args).data());
- execvp(program.c_str(), stringsToCharPtrs(args).data());
+ throw SysError("unable to execute '%s'", program);
+}
- throw SysError("unable to execute '%s'", program);
- }
-};
+}
-struct CmdShell : InstallablesCommand, RunCommon, MixEnvironment
+struct CmdShell : InstallablesCommand, MixEnvironment
{
using InstallablesCommand::run;
@@ -125,13 +124,13 @@ struct CmdShell : InstallablesCommand, RunCommon, MixEnvironment
Strings args;
for (auto & arg : command) args.push_back(arg);
- runProgram(store, *command.begin(), args);
+ runProgramInStore(store, *command.begin(), args);
}
};
static auto rCmdShell = registerCommand<CmdShell>("shell");
-struct CmdRun : InstallableCommand, RunCommon
+struct CmdRun : InstallableCommand
{
using InstallableCommand::run;
@@ -183,7 +182,7 @@ struct CmdRun : InstallableCommand, RunCommon
Strings allArgs{app.program};
for (auto & i : args) allArgs.push_back(i);
- runProgram(store, app.program, allArgs);
+ runProgramInStore(store, app.program, allArgs);
}
};