]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: move X-mount.mkdir to separate file
authorKarel Zak <kzak@redhat.com>
Mon, 23 May 2022 10:15:29 +0000 (12:15 +0200)
committerKarel Zak <kzak@redhat.com>
Tue, 3 Jan 2023 11:53:12 +0000 (12:53 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
libmount/src/Makemodule.am
libmount/src/context_mount.c
libmount/src/hook_mkdir.c [new file with mode: 0644]
libmount/src/hooks.c
libmount/src/mountP.h

index 2174eeb4c9e953165a3ddf66c160bda32b8b408c..1e7ec24d0da043db035159f7d1626d65e1226e84 100644 (file)
@@ -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
index 55b94cacb4fe6f5b2f632c0202c905bb75c93606..990cc11f82738f839ab34a19257043c5652ead82 100644 (file)
@@ -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 (file)
index 0000000..ba1a8a4
--- /dev/null
@@ -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 <kzak@redhat.com>
+ *
+ * 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
+};
index e5307bd32943dc3d30f87eb596772dae3351a658..5e6327c6e592bf255a5f9d9fdeefd91fd91811ed 100644 (file)
 #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
 };
index ffc37ac5dfb9eea1cacffa505ba04c22ed623ec6..29dcba82fac13d63fbda798fc9cd669852bb63d5 100644 (file)
@@ -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);