From 701c69617e50ed8c15bc2c5bc7bf6eee1cb04b23 Mon Sep 17 00:00:00 2001 From: Ondrej Oprala Date: Fri, 21 Dec 2012 14:45:46 +0100 Subject: [PATCH] mount: add support for x-mount.mkdir[=] option If the target directory (mountpoint) does not exist then mount(8) will create it before mount. is executed or mount(2) syscall is called. Co-Author: Karel Zak Signed-off-by: Ondrej Oprala Signed-off-by: Karel Zak --- Documentation/TODO | 2 - libmount/src/context.c | 52 +++++++++++++++++++ sys-utils/mount.8 | 7 +++ tests/expected/libmount/context-x-mount.mkdir | 1 + tests/ts/libmount/context | 10 ++++ 5 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 tests/expected/libmount/context-x-mount.mkdir diff --git a/Documentation/TODO b/Documentation/TODO index 694e9a7d6a..50c95191e4 100644 --- a/Documentation/TODO +++ b/Documentation/TODO @@ -26,8 +26,6 @@ libmount (mount/umount) (all this already supported by libmount) - - add x-mount-mkdir mount option to libmount to allow "mkdir /mountpoint" - - support MS_PROPAGATION flags in fstab -- note that kernel assumes that these flags are not mixed with another mount flags, it means that: diff --git a/libmount/src/context.c b/libmount/src/context.c index 3269b0beb8..35c2f04b08 100644 --- a/libmount/src/context.c +++ b/libmount/src/context.c @@ -1368,6 +1368,47 @@ int mnt_context_prepare_srcpath(struct libmnt_context *cxt) return 0; } +/* create a mountpoint if x-mount.mkdir[=] specified */ +static int mkdir_target(const char *tgt, struct libmnt_fs *fs) +{ + char *mstr = NULL; + size_t mstr_sz = 0; + mode_t mode = 0; + struct stat st; + int rc; + + assert(tgt); + assert(fs); + + if (mnt_optstr_get_option(fs->user_optstr, "x-mount.mkdir", &mstr, &mstr_sz) != 0) + return 0; + if (stat(tgt, &st) == 0) + return 0; + + if (mstr && mstr_sz) { + char *end = NULL; + + errno = 0; + mode = strtol(mstr, &end, 8); + + if (errno || !end || mstr + mstr_sz != end) { + DBG(CXT, mnt_debug("failed to parse mkdir mode '%s'", mstr)); + return -MNT_ERR_MOUNTOPT; + } + } + + if (!mode) + mode = S_IRWXU | /* 0755 */ + S_IRGRP | S_IXGRP | + S_IROTH | S_IXOTH; + + rc = mkdir_p(tgt, mode); + if (rc) + DBG(CXT, mnt_debug("mkdir %s failed: %m", tgt)); + + return rc; +} + int mnt_context_prepare_target(struct libmnt_context *cxt) { const char *tgt; @@ -1387,6 +1428,17 @@ int mnt_context_prepare_target(struct libmnt_context *cxt) if (!tgt) return 0; + /* mkdir target */ + if (cxt->action == MNT_ACT_MOUNT + && !mnt_context_is_restricted(cxt) + && cxt->user_mountflags & MNT_MS_XCOMMENT) { + + rc = mkdir_target(tgt, cxt->fs); + if (rc) + return rc; /* mkdir or parse error */ + } + + /* canonicalize the path */ cache = mnt_context_get_cache(cxt); if (cache) { char *path = mnt_resolve_path(tgt, cache); diff --git a/sys-utils/mount.8 b/sys-utils/mount.8 index 5f77f18364..add9818fab 100644 --- a/sys-utils/mount.8 +++ b/sys-utils/mount.8 @@ -1105,6 +1105,13 @@ applications specific options. These options are not stored to mtab file, send to mount. helpers or .B mount(2) system call. The suggested format is x-.