#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
-#include "compat.h"
#include "util.h"
#include "pathconfig.h"
#include <assert.h>
#include <ctype.h>
#include <sys/wait.h>
+#include <libgen.h>
#define MNTPOINT "/etc"
#define OPTION_FSTAB 1027
#define OPTION_CHROOT 1028
#define OPTION_SECURE 1029
+#define OPTION_RBIND 1030
static struct option const
CMDLINE_OPTIONS[] = {
{ "fstab", required_argument, 0, OPTION_FSTAB },
{ "chroot", required_argument, 0, OPTION_CHROOT },
{ "secure", no_argument, 0, OPTION_SECURE },
+ { "rbind", no_argument, 0, OPTION_RBIND },
{ 0, 0, 0, 0 }
};
+#ifndef MS_REC
+# define MS_REC 0x4000
+#endif
+
static struct FstabOptions {
char const * const opt;
unsigned long const or_flag;
unsigned long const and_flag;
bool const is_dflt;
} const FSTAB_OPTIONS[] = {
+ { "rbind", MS_BIND|MS_REC, ~0, false },
{ "bind", MS_BIND, ~0, false },
{ "move", MS_MOVE, ~0, false },
#if 0
static void
showHelp(int fd, char const *cmd, int res)
{
+ VSERVER_DECLARE_CMD(cmd);
+
WRITE_MSG(fd, "Usage: ");
WRITE_STR(fd, cmd);
WRITE_MSG(fd,
- " [--help] [--version] [--bind] [--move] [-t <type>] [-n]\n"
+ " [--help] [--version] [--bind] [--move] [--rbind] [-t <type>] [-n]\n"
" [--mtab <filename>] [--fstab <filename>] [--chroot <dirname>] \n"
" [--secure] -a|([-o <options>] [--] <src> <dst>)\n\n"
"Executes mount-operations in the given chroot-dir: it assumes sources in the\n"
static int
writeX(int fd, void const *buf, size_t len)
{
- if (write(fd, buf, len)!=len) return -1;
+ if ((size_t)(write(fd, buf, len))!=len) return -1;
return 0;
}
if (mnt->flags & MS_BIND) argv[idx++] = "--bind";
else if (mnt->flags & MS_MOVE) argv[idx++] = "--move";
- if (mnt->data) {
+ if (mnt->data &&
+ strcmp(mnt->data, "defaults")!=0) {
argv[idx++] = "-o";
argv[idx++] = mnt->data;
}
}
}
- if (mnt->flags&MS_BIND) {
+ if (mnt->flags & (MS_BIND|MS_MOVE)) {
if (mount(mnt->src, ".",
mnt->type ? mnt->type : "",
mnt->flags, mnt->data)==-1) {
while (isspace(*PTR)) ++PTR
static enum {prDOIT, prFAIL, prIGNORE}
-parseFstabLine(struct MountInfo *info, char *buf, struct Options const *opt)
+parseFstabLine(struct MountInfo *info, char *buf)
{
while (isspace(*buf)) ++buf;
- if (*buf=='#') return prIGNORE;
+ if (*buf=='#' || *buf=='\0') return prIGNORE;
info->src = buf;
MOVE_TO_NEXT_FIELD(buf, false);
}
{
- char buf[len+1];
+ char buf[len+2];
char *ptr, *ptrptr;
if (read(fd, buf, len+1)!=len) {
perror("read()");
goto err1;
}
- buf[len] = '\0';
+ buf[len] = '#'; // workaround for broken dietlibc strtok_r()
+ // implementation
+ buf[len+1] = '\0';
ptr = strtok_r(buf, "\n", &ptrptr);
while (ptr) {
struct MountInfo mnt;
char * new_ptr = strtok_r(0, "\n", &ptrptr);
- switch (parseFstabLine(&mnt, ptr, opt)) {
+ switch (parseFstabLine(&mnt, ptr)) {
case prFAIL :
- WRITE_MSG(2, "Failed to parse/mount fstab-line beginning with '");
+ WRITE_MSG(2, "Failed to parse fstab-line beginning with '");
WRITE_STR(2, ptr);
WRITE_MSG(2, "'\n");
goto err1;
};
struct Options opt = {
- .mtab = "/etc/mtab",
- .fstab = "/etc/fstab",
- .rootdir = 0,
- .ignore_mtab = false,
- .mount_all = false,
- .is_secure = false,
-
- .cur_rootdir_fd = open("/", O_RDONLY|O_DIRECTORY)
+ .mtab = "/etc/mtab",
+ .fstab = "/etc/fstab",
+ .rootdir = 0,
+ .ignore_mtab = false,
+ .mount_all = false,
+ .is_secure = false,
+ .cur_rootdir_fd = -1
};
+ opt.cur_rootdir_fd = open("/", O_RDONLY|O_DIRECTORY);
+
if (opt.cur_rootdir_fd==-1) {
perror("open(\"/\")");
return EXIT_FAILURE;
if (c==-1) break;
switch (c) {
- case 'h' : showHelp(2, argv[0], 0);
+ case 'h' : showHelp(1, argv[0], 0);
case 'v' : showVersion();
case 't' : mnt.type = optarg; break;
case 'n' : opt.ignore_mtab = true; break;
case 'a' : opt.mount_all = true; break;
case 'o' : mnt.data = optarg; break;
+ case OPTION_RBIND : mnt.flags |= MS_REC; /*@fallthrough@*/
case OPTION_BIND : mnt.flags |= MS_BIND; break;
case OPTION_MOVE : mnt.flags |= MS_MOVE; break;
case OPTION_MTAB : opt.mtab = optarg; break;