Fork me on GitHub

plash mount


Usage

plash mount IMAGE_ID MOUNTPOINT [ CHANGESDIR ]

Description

Mount a container-filesystem. Changes to the filesystem will be written to
CHANGESDIR.

Tested Behaviour

#!/bin/bash
set eux


• Can mount a container

tmp=$(mktemp -d)
plash sudo sh -c "
plash mount 1 $tmp
grep  $tmp' '  /proc/mounts >/dev/null || {
  echo 'Could not find mountpoint in /proc/mounts '
  exit 1
}
test -d $tmp/usr
test -d $tmp/bin
test -d $tmp/var
"

• check bad chars

tmp=$(mktemp -d)
changesdir=$tmp/'!@#$%^&*()'
mkdir $tmp/mp
mkdir $changesdir
(! plash mount 1 /tmp/mp "$changesdir" )

Source Code


#define _GNU_SOURCE

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <plash.h>

#define USAGE "usage: plash mount IMAGE_ID MOUNTPOINT [ CHANGESDIR ]\n"

#define CHANGESDIR_ALLOWED_CHARS                                               \
  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./-_"

char *prepare_lowerdir(char *image_id) {
  char *lowerdir = "";
  char *plash_data = pl_call("data");
  char *nodepath = pl_call("nodepath", image_id);
  int offset = strlen(plash_data) + strlen("/layer/");
  if (strlen(nodepath) < offset) {
    pl_fatal("Unexpected interal error: nodepath command output is shorter "
             "than data command output");
  }
  char *curr;
  char *str = nodepath + offset;
  while ((curr = strsep(&str, "/"))) {
    asprintf(&lowerdir, "%s/index/%s/_data/root:%s", plash_data, curr,
             lowerdir) != -1 ||
        pl_fatal("asprintf");
  }
  lowerdir[strlen(lowerdir) - 1] = '\0'; // chop the last ":"
  return lowerdir;
}

char *prepare_workdir(char *changesdir) {
  char *workdir;
  asprintf(&workdir, "%s/work", changesdir) != -1 || pl_fatal("asprintf");
  if (mkdir(workdir, 0755) == -1 && errno != EEXIST)
    pl_fatal("mkdir");
  return workdir;
}

char *prepare_datadir(char *changesdir) {
  char *datadir;
  asprintf(&datadir, "%s/data", changesdir) != -1 || pl_fatal("asprintf");
  if (mkdir(datadir, 0755) == -1 && errno != EEXIST)
    pl_fatal("mkdir");
  return datadir;
}

void validate_changesdir(char *changesdir) {
  int found_in_allowed;
  for (size_t i = 0; changesdir[i]; i++) {
    found_in_allowed = 0;
    for (size_t j = 0; strlen(CHANGESDIR_ALLOWED_CHARS) > j; j++) {
      if (changesdir[i] == CHANGESDIR_ALLOWED_CHARS[j]) {
        found_in_allowed = 1;
      }
    }
    if (!found_in_allowed) {
      pl_fatal("Not allowed charachter found in changesdir: %c", changesdir[i]);
    }
  }
}

int mount_main(int argc, char *argv[]) {

  if (argc < 3) {
    {
      fputs(USAGE, stderr);
      return EXIT_FAILURE;
    }
  }
  char *image_id = argv[1];
  char *mountpoint = argv[2];
  char *changesdir = argv[3];

  char *mount_opts;

  if (changesdir != NULL) {
    validate_changesdir(changesdir);
    if (mkdir(changesdir, 0755) == -1 && errno != EEXIST)
      pl_fatal("mkdir %s", changesdir);
    asprintf(&mount_opts, "lowerdir=%s,workdir=%s,upperdir=%s",
             prepare_lowerdir(image_id), prepare_workdir(changesdir),
             prepare_datadir(changesdir)) != -1 ||
        pl_fatal("asprintf");
  } else {
    asprintf(&mount_opts, "lowerdir=%s", prepare_lowerdir(image_id)) != -1 ||
        pl_fatal("asprintf");
  }
  execlp("mount", "mount", "-t", "overlay", "overlay", "-o", mount_opts,
         mountpoint, NULL);
  pl_fatal("execlp");
  return EXIT_FAILURE;
}