From: Karel Zak Date: Mon, 23 May 2022 09:45:57 +0000 (+0200) Subject: libmount: move mount-only functions to context_mount.c X-Git-Tag: v2.39-rc1~346 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a603f2a4562ae0e47f3aa52011a3c2b2206f2568;p=thirdparty%2Futil-linux.git libmount: move mount-only functions to context_mount.c Signed-off-by: Karel Zak --- diff --git a/libmount/src/context.c b/libmount/src/context.c index 2178627a7f..840549d86e 100644 --- a/libmount/src/context.c +++ b/libmount/src/context.c @@ -37,7 +37,6 @@ */ #include "mountP.h" -#include "fileutils.h" #include "strutils.h" #include "namespace.h" @@ -1901,174 +1900,6 @@ end: return rc; } -static int is_subdir_required(struct libmnt_context *cxt, int *rc) -{ - char *dir; - size_t sz; - - assert(cxt); - assert(rc); - - *rc = 0; - - if (!cxt->fs - || !cxt->fs->user_optstr - || mnt_optstr_get_option(cxt->fs->user_optstr, - "X-mount.subdir", &dir, &sz) != 0) - return 0; - - if (dir && *dir == '"') - dir++, sz-=2; - - if (!dir || sz < 1) { - DBG(CXT, ul_debug("failed to parse X-mount.subdir '%s'", dir)); - *rc = -MNT_ERR_MOUNTOPT; - } else { - cxt->subdir = strndup(dir, sz); - if (!cxt->subdir) - *rc = -ENOMEM; - - DBG(CXT, ul_debug("subdir %s wanted", dir)); - } - - return *rc == 0; -} - -static int is_mkdir_required(const char *tgt, struct libmnt_fs *fs, mode_t *mode, int *rc) -{ - char *mstr = NULL; - size_t mstr_sz = 0; - struct stat st; - - assert(tgt); - assert(fs); - assert(mode); - assert(rc); - - *mode = 0; - *rc = 0; - - if (mnt_optstr_get_option(fs->user_optstr, "X-mount.mkdir", &mstr, &mstr_sz) != 0 && - mnt_optstr_get_option(fs->user_optstr, "x-mount.mkdir", &mstr, &mstr_sz) != 0) /* obsolete */ - return 0; - - if (mnt_stat_mountpoint(tgt, &st) == 0) - return 0; - - DBG(CXT, ul_debug("mkdir %s (%s) wanted", tgt, mstr)); - - if (mstr && mstr_sz) { - char *end = NULL; - - if (*mstr == '"') - mstr++, mstr_sz-=2; - - errno = 0; - *mode = strtol(mstr, &end, 8); - - if (errno || !end || mstr + mstr_sz != end) { - DBG(CXT, ul_debug("failed to parse mkdir mode '%s'", mstr)); - *rc = -MNT_ERR_MOUNTOPT; - return 0; - } - } - - if (!*mode) - *mode = S_IRWXU | /* 0755 */ - S_IRGRP | S_IXGRP | - S_IROTH | S_IXOTH; - - return 1; -} - -int mnt_context_prepare_target(struct libmnt_context *cxt) -{ - const char *tgt, *prefix; - int rc = 0; - struct libmnt_ns *ns_old; - mode_t mode = 0; - - assert(cxt); - assert(cxt->fs); - assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED)); - - DBG(CXT, ul_debugobj(cxt, "--> preparing target path")); - - tgt = mnt_fs_get_target(cxt->fs); - if (!tgt) - return 0; - - /* apply prefix */ - prefix = mnt_context_get_target_prefix(cxt); - if (prefix) { - const char *p = *tgt == '/' ? tgt + 1 : tgt; - - if (!*p) - /* target is "/", use "/prefix" */ - rc = mnt_fs_set_target(cxt->fs, prefix); - else { - char *path = NULL; - - if (asprintf(&path, "%s/%s", prefix, p) <= 0) - rc = -ENOMEM; - else { - rc = mnt_fs_set_target(cxt->fs, path); - free(path); - } - } - if (rc) - return rc; - tgt = mnt_fs_get_target(cxt->fs); - } - - ns_old = mnt_context_switch_target_ns(cxt); - if (!ns_old) - return -MNT_ERR_NAMESPACE; - - /* X-mount.mkdir target */ - if (cxt->action == MNT_ACT_MOUNT - && (cxt->user_mountflags & MNT_MS_XCOMMENT || - cxt->user_mountflags & MNT_MS_XFSTABCOMM) - && is_mkdir_required(tgt, cxt->fs, &mode, &rc)) { - - /* supported only for root or non-suid mount(8) */ - if (!mnt_context_is_restricted(cxt)) { - rc = ul_mkdir_p(tgt, mode); - if (rc) - DBG(CXT, ul_debug("mkdir %s failed: %m", tgt)); - } else - rc = -EPERM; - } - - /* canonicalize the path */ - if (rc == 0) { - struct libmnt_cache *cache = mnt_context_get_cache(cxt); - - if (cache) { - char *path = mnt_resolve_path(tgt, cache); - if (path && strcmp(path, tgt) != 0) - rc = mnt_fs_set_target(cxt->fs, path); - } - } - - /* X-mount.subdir= target */ - if (rc == 0 - && cxt->action == MNT_ACT_MOUNT - && (cxt->user_mountflags & MNT_MS_XFSTABCOMM) - && is_subdir_required(cxt, &rc)) { - - DBG(CXT, ul_debugobj(cxt, "subdir %s required", cxt->subdir)); - } - - - if (!mnt_context_switch_ns(cxt, ns_old)) - return -MNT_ERR_NAMESPACE; - - DBG(CXT, ul_debugobj(cxt, "final target '%s' [rc=%d]", - mnt_fs_get_target(cxt->fs), rc)); - return rc; -} - /* Guess type, but not set to cxt->fs, always use free() for the result. It's * no error when we're not able to guess a filesystem type. Note that error * does not mean that result in @type is NULL. diff --git a/libmount/src/context_mount.c b/libmount/src/context_mount.c index 6e8464a337..55b94cacb4 100644 --- a/libmount/src/context_mount.c +++ b/libmount/src/context_mount.c @@ -27,6 +27,7 @@ #include "linux_version.h" #include "mountP.h" #include "strutils.h" +#include "fileutils.h" #if defined(HAVE_LIBSELINUX) || defined(HAVE_SMACK) struct libmnt_optname { @@ -853,6 +854,175 @@ static int parse_ownership_mode(struct libmnt_context *cxt) return 0; } +static int is_subdir_required(struct libmnt_context *cxt, int *rc) +{ + char *dir; + size_t sz; + + assert(cxt); + assert(rc); + + *rc = 0; + + if (!cxt->fs + || !cxt->fs->user_optstr + || mnt_optstr_get_option(cxt->fs->user_optstr, + "X-mount.subdir", &dir, &sz) != 0) + return 0; + + if (dir && *dir == '"') + dir++, sz-=2; + + if (!dir || sz < 1) { + DBG(CXT, ul_debug("failed to parse X-mount.subdir '%s'", dir)); + *rc = -MNT_ERR_MOUNTOPT; + } else { + cxt->subdir = strndup(dir, sz); + if (!cxt->subdir) + *rc = -ENOMEM; + + DBG(CXT, ul_debug("subdir %s wanted", dir)); + } + + return *rc == 0; +} + +static int is_mkdir_required(const char *tgt, struct libmnt_fs *fs, mode_t *mode, int *rc) +{ + char *mstr = NULL; + size_t mstr_sz = 0; + struct stat st; + + assert(tgt); + assert(fs); + assert(mode); + assert(rc); + + *mode = 0; + *rc = 0; + + if (mnt_optstr_get_option(fs->user_optstr, "X-mount.mkdir", &mstr, &mstr_sz) != 0 && + mnt_optstr_get_option(fs->user_optstr, "x-mount.mkdir", &mstr, &mstr_sz) != 0) /* obsolete */ + return 0; + + if (mnt_stat_mountpoint(tgt, &st) == 0) + return 0; + + DBG(CXT, ul_debug("mkdir %s (%s) wanted", tgt, mstr)); + + if (mstr && mstr_sz) { + char *end = NULL; + + if (*mstr == '"') + mstr++, mstr_sz-=2; + + errno = 0; + *mode = strtol(mstr, &end, 8); + + if (errno || !end || mstr + mstr_sz != end) { + DBG(CXT, ul_debug("failed to parse mkdir mode '%s'", mstr)); + *rc = -MNT_ERR_MOUNTOPT; + return 0; + } + } + + if (!*mode) + *mode = S_IRWXU | /* 0755 */ + S_IRGRP | S_IXGRP | + S_IROTH | S_IXOTH; + + return 1; +} + + +static int prepare_target(struct libmnt_context *cxt) +{ + const char *tgt, *prefix; + int rc = 0; + struct libmnt_ns *ns_old; + mode_t mode = 0; + + assert(cxt); + assert(cxt->fs); + assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED)); + + DBG(CXT, ul_debugobj(cxt, "--> preparing target path")); + + tgt = mnt_fs_get_target(cxt->fs); + if (!tgt) + return 0; + + /* apply prefix */ + prefix = mnt_context_get_target_prefix(cxt); + if (prefix) { + const char *p = *tgt == '/' ? tgt + 1 : tgt; + + if (!*p) + /* target is "/", use "/prefix" */ + rc = mnt_fs_set_target(cxt->fs, prefix); + else { + char *path = NULL; + + if (asprintf(&path, "%s/%s", prefix, p) <= 0) + rc = -ENOMEM; + else { + rc = mnt_fs_set_target(cxt->fs, path); + free(path); + } + } + if (rc) + return rc; + tgt = mnt_fs_get_target(cxt->fs); + } + + ns_old = mnt_context_switch_target_ns(cxt); + if (!ns_old) + return -MNT_ERR_NAMESPACE; + + /* X-mount.mkdir target */ + if (cxt->action == MNT_ACT_MOUNT + && (cxt->user_mountflags & MNT_MS_XCOMMENT || + cxt->user_mountflags & MNT_MS_XFSTABCOMM) + && is_mkdir_required(tgt, cxt->fs, &mode, &rc)) { + + /* supported only for root or non-suid mount(8) */ + if (!mnt_context_is_restricted(cxt)) { + rc = ul_mkdir_p(tgt, mode); + if (rc) + DBG(CXT, ul_debug("mkdir %s failed: %m", tgt)); + } else + rc = -EPERM; + } + + /* canonicalize the path */ + if (rc == 0) { + struct libmnt_cache *cache = mnt_context_get_cache(cxt); + + if (cache) { + char *path = mnt_resolve_path(tgt, cache); + if (path && strcmp(path, tgt) != 0) + rc = mnt_fs_set_target(cxt->fs, path); + } + } + + /* X-mount.subdir= target */ + if (rc == 0 + && cxt->action == MNT_ACT_MOUNT + && (cxt->user_mountflags & MNT_MS_XFSTABCOMM) + && is_subdir_required(cxt, &rc)) { + + DBG(CXT, ul_debugobj(cxt, "subdir %s required", cxt->subdir)); + } + + + if (!mnt_context_switch_ns(cxt, ns_old)) + return -MNT_ERR_NAMESPACE; + + DBG(CXT, ul_debugobj(cxt, "final target '%s' [rc=%d]", + mnt_fs_get_target(cxt->fs), rc)); + return rc; +} + /** * mnt_context_prepare_mount: * @cxt: context @@ -898,7 +1068,7 @@ int mnt_context_prepare_mount(struct libmnt_context *cxt) if (!rc) rc = mnt_context_guess_fstype(cxt); if (!rc) - rc = mnt_context_prepare_target(cxt); + rc = prepare_target(cxt); if (!rc) rc = parse_ownership_mode(cxt); if (!rc) diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h index 98e40d23a1..ffc37ac5df 100644 --- a/libmount/src/mountP.h +++ b/libmount/src/mountP.h @@ -489,7 +489,6 @@ extern int mnt_context_get_mountinfo_for_target(struct libmnt_context *cxt, struct libmnt_table **mountinfo, const char *tgt); extern int mnt_context_prepare_srcpath(struct libmnt_context *cxt); -extern int mnt_context_prepare_target(struct libmnt_context *cxt); extern int mnt_context_guess_srcpath_fstype(struct libmnt_context *cxt, char **type); extern int mnt_context_guess_fstype(struct libmnt_context *cxt); extern int mnt_context_prepare_helper(struct libmnt_context *cxt,