From: Karel Zak Date: Mon, 23 May 2022 10:15:29 +0000 (+0200) Subject: libmount: move X-mount.mkdir to separate file X-Git-Tag: v2.39-rc1~345 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=093f224587312011183a4259abc4f74ff46792c0;p=thirdparty%2Futil-linux.git libmount: move X-mount.mkdir to separate file Signed-off-by: Karel Zak --- diff --git a/libmount/src/Makemodule.am b/libmount/src/Makemodule.am index 2174eeb4c9..1e7ec24d0d 100644 --- a/libmount/src/Makemodule.am +++ b/libmount/src/Makemodule.am @@ -33,6 +33,7 @@ libmount_la_SOURCES += \ libmount/src/context_mount.c \ libmount/src/context_umount.c \ libmount/src/hook_mount_legacy.c \ + libmount/src/hook_mkdir.c \ libmount/src/monitor.c if HAVE_BTRFS diff --git a/libmount/src/context_mount.c b/libmount/src/context_mount.c index 55b94cacb4..990cc11f82 100644 --- a/libmount/src/context_mount.c +++ b/libmount/src/context_mount.c @@ -27,7 +27,6 @@ #include "linux_version.h" #include "mountP.h" #include "strutils.h" -#include "fileutils.h" #if defined(HAVE_LIBSELINUX) || defined(HAVE_SMACK) struct libmnt_optname { @@ -887,60 +886,11 @@ static int is_subdir_required(struct libmnt_context *cxt, int *rc) 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); @@ -980,19 +930,7 @@ static int prepare_target(struct libmnt_context *cxt) 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; - } + rc = mnt_context_call_hooks(cxt, MNT_STAGE_PREP_TARGET); /* canonicalize the path */ if (rc == 0) { diff --git a/libmount/src/hook_mkdir.c b/libmount/src/hook_mkdir.c new file mode 100644 index 0000000000..ba1a8a4ccb --- /dev/null +++ b/libmount/src/hook_mkdir.c @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * This file is part of libmount from util-linux project. + * + * Copyright (C) 2022 Karel Zak + * + * libmount is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + */ + +#include "mountP.h" +#include "fileutils.h" + +static int hook_prepare_target(struct libmnt_context *cxt, const struct libmnt_hookset *hs, void *data); + +static int hookset_init(struct libmnt_context *cxt, const struct libmnt_hookset *hs) +{ + DBG(HOOK, ul_debugobj(hs, "init '%s'", hs->name)); + + return mnt_context_append_hook(cxt, hs, + MNT_STAGE_PREP_TARGET, NULL, hook_prepare_target); +} + +static int hookset_deinit(struct libmnt_context *cxt, const struct libmnt_hookset *hs) +{ + void *data = NULL; + + DBG(HOOK, ul_debugobj(hs, "deinit '%s'", hs->name)); + + /* remove all our hooks and free hook data */ + while (mnt_context_remove_hook(cxt, hs, 0, &data) == 0) { + if (data) + free(data); + data = NULL; + } + + return 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(HOOK, 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(HOOK, 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 hook_prepare_target( + struct libmnt_context *cxt, + const struct libmnt_hookset *hs, + void *data __attribute__((__unused__))) +{ + int rc = 0; + mode_t mode = 0; + const char *tgt; + + assert(cxt); + + tgt = mnt_fs_get_target(cxt->fs); + if (!tgt) + return 0; + + 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(HOOK, ul_debugobj(hs, "mkdir %s failed: %m", tgt)); + } else + rc = -EPERM; + } + + return rc; +} + + +const struct libmnt_hookset hookset_mkdir = +{ + .name = "__mkdir", + .init = hookset_init, + .deinit = hookset_deinit +}; diff --git a/libmount/src/hooks.c b/libmount/src/hooks.c index e5307bd329..5e6327c6e5 100644 --- a/libmount/src/hooks.c +++ b/libmount/src/hooks.c @@ -19,8 +19,10 @@ #include "mountP.h" /* built-in hooksets */ -static const struct libmnt_hookset *hooksets[] = { +static const struct libmnt_hookset *hooksets[] = +{ #ifdef __linux__ + &hookset_mkdir, &hookset_mount_legacy #endif }; diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h index ffc37ac5df..29dcba82fa 100644 --- a/libmount/src/mountP.h +++ b/libmount/src/mountP.h @@ -301,6 +301,7 @@ struct libmnt_hookset { /* built-in hooks */ extern const struct libmnt_hookset hookset_mount_legacy; +extern const struct libmnt_hookset hookset_mkdir; extern int mnt_context_init_hooksets(struct libmnt_context *cxt);