Fork me on GitHub

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;
}