plash with-mount
Usage
plash with-mount CONTAINER [ CMD1 [ CMD2 ... ] ]
Description
Execute parameters inside a mounted container. Default parameter is the
default shell. Mounting happens inside an isolated mount namespace.
Example to get how much disk space a container is using:
$ plash with-mount 70 du -sh
7,2M .
Tested Behaviour
#!/bin/bash
set -xeu
• Simple invocation succeeds
plash with-mount 1 printf hi
• Listing an images directories succeeds
out=$(plash with-mount 1 ls | xargs)
[[ " $out " == *' home '* ]]
[[ " $out " == *' usr '* ]]
[[ " $out " == *' bin '* ]]
• Bad exit status will get propagated
(! plash with-mount 1 sh -c 'exit 7')
• No mountspace polution
before=$(cat /proc/mounts | grep "/index/1" | wc -l)
plash with-mount 1 true
(! plash with-mount 1 false)
after=$(cat /proc/mounts | grep "/index/1" | wc -l)
test $before = $after
• You can tar out the image /dev/null
plash with-mount 1 tar -cf - . > /dev/null
• Comprehensive error message when an unknown command is given
set +e
out=$(plash with-mount 1 cmdnotfound 2>&1)
set -e
[[ "$out" == *"cmdnotfound: command not found"* ]]
• No command leads to shell
test "$(echo "echo itshell" | plash with-mount 1)" = itshell
Source Code
#define USAGE "usage: plash with-mount CONTAINER [ CMD1 [ CMD2 ... ] ]\n"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <plash.h>
int with_mount_main(int argc, char *argv[]) {
if (argc < 2) {
fputs(USAGE, stderr);
return EXIT_FAILURE;
}
char *image_id = argv[1];
char *cmd = argv[2];
pl_unshare_user();
pl_unshare_mount();
char *mountpoint = pl_call("mkdtemp");
pl_call("mount", image_id, mountpoint);
if (chdir(mountpoint) == -1)
pl_fatal("chdir");
if (cmd == NULL) {
char *default_root_shell = pl_get_default_root_shell();
execlp(default_root_shell, default_root_shell, NULL);
pl_fatal("execlp");
} else {
argv++; // chop argv[0]
argv++; // chop the image_id arg;
execvp(*argv, argv);
if (errno == ENOENT) {
fprintf(stderr, "%s: command not found\n", *argv);
return 127;
}
pl_fatal("execvp");
}
return EXIT_SUCCESS;
}