summaryrefslogtreecommitdiff
path: root/sandboxlib/chroot.py
diff options
context:
space:
mode:
Diffstat (limited to 'sandboxlib/chroot.py')
-rw-r--r--sandboxlib/chroot.py34
1 files changed, 27 insertions, 7 deletions
diff --git a/sandboxlib/chroot.py b/sandboxlib/chroot.py
index 3fe1857..157b9fe 100644
--- a/sandboxlib/chroot.py
+++ b/sandboxlib/chroot.py
@@ -13,21 +13,41 @@
# with this program. If not, see <http://www.gnu.org/licenses/>.
-'''Execute command in a sandbox, using 'chroot'.'''
+'''Execute command in a sandbox, using os.chroot().
+The code would be simpler if we just used the 'chroot' program, but it's not
+always practical to do that. First, it may not be installed. Second, we can't
+set the working directory of the program inside the chroot, unless we assume
+that the sandbox contains a shell and we do some hack like running
+`/bin/sh -c "cd foo && command"`. It's better to call the kernel directly.
+'''
+
+
+import os
import subprocess
+import sys
import sandboxlib
-def run_sandbox(rootfs_path, command, extra_env=None):
+def run_sandbox(rootfs_path, command, cwd=None, extra_env=None):
if type(command) == str:
command = [command]
- env = sandboxlib.BASE_ENVIRONMENT.copy()
- if extra_env is not None:
- env.update(extra_env)
+ env = sandboxlib.environment_vars(extra_env)
+
+ pid = os.fork()
+ if pid == 0:
+ # Child process. It's a bit messy that we create a child process and
+ # then a second child process, but it saves duplicating stuff from the
+ # 'subprocess' module.
+
+ # FIXME: you gotta be root for this one.
+ os.chroot(rootfs_path)
- # FIXME: you gotta be root for this one.
- subprocess.call(['chroot', rootfs_path] + command)
+ result = subprocess.call(command, cwd=cwd, env=env)
+ os._exit(result)
+ else:
+ # Parent process. Wait for child to exit.
+ os.waitpid(pid, 0)