]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: support VFS flags attributes clear
authorKarel Zak <kzak@redhat.com>
Thu, 22 Sep 2022 09:05:53 +0000 (11:05 +0200)
committerKarel Zak <kzak@redhat.com>
Tue, 3 Jan 2023 11:58:42 +0000 (12:58 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
libmount/src/hook_mount.c
libmount/src/mountP.h
libmount/src/optlist.c

index d4be4d73704108518f8525a59a3280e0c4c59c3a..abfd00ebf790e62d854fad31bfe86d2192db2c45 100644 (file)
@@ -137,7 +137,7 @@ static int hook_set_vfsflags(struct libmnt_context *cxt,
        struct libmnt_optlist *ol;
        struct mount_attr attr = { .attr_clr = 0 };
        unsigned int callflags = AT_EMPTY_PATH;
-       uint64_t mask = 0;
+       uint64_t set = 0, clr = 0;
        int rc;
 
        api = get_sysapi(cxt, hs);
@@ -148,15 +148,17 @@ static int hook_set_vfsflags(struct libmnt_context *cxt,
        if (!ol)
                return -ENOMEM;
 
-       rc = mnt_optlist_get_attrs(ol, &mask);
+       rc = mnt_optlist_get_attrs(ol, &set, &clr);
        if (rc)
                return rc;
 
        if (mnt_optlist_is_recursive(ol))
                callflags |= AT_RECURSIVE;
 
-       DBG(HOOK, ul_debugobj(hs, "mount_setattr(set=0x%" PRIx64")", mask));
-       attr.attr_set = mask;
+       DBG(HOOK, ul_debugobj(hs,
+                       "mount_setattr(set=0x%08" PRIx64" clr=0x%08" PRIx64")", set, clr));
+       attr.attr_set = set;
+       attr.attr_clr = clr;
 
        rc = mount_setattr(api->fd_tree, "", callflags, &attr, sizeof(attr));
        set_syscall_status(cxt, "move_setattr", rc == 0);
@@ -287,7 +289,7 @@ static int hook_prepare(struct libmnt_context *cxt,
 {
        struct libmnt_optlist *ol;
        unsigned long flags = 0;
-       uint64_t attrs = 0;
+       uint64_t set = 0, clr = 0;
        int rc = 0;
 
        assert(cxt);
@@ -304,7 +306,7 @@ static int hook_prepare(struct libmnt_context *cxt,
 
        /* MOUNT_ATTR_* flags for mount_setattr() */
        if (!rc)
-               rc = mnt_optlist_get_attrs(ol, &attrs);
+               rc = mnt_optlist_get_attrs(ol, &set, &clr);
 
        /* open_tree() or fsopen() */
        if (!rc)
@@ -322,7 +324,7 @@ static int hook_prepare(struct libmnt_context *cxt,
                                        hook_reconfigure_mount);
 
        /* call mount_setattr() */
-       if (!rc && attrs != 0)
+       if (!rc && (set != 0 || clr != 0))
                rc = mnt_context_append_hook(cxt, hs, MNT_STAGE_MOUNT, NULL,
                                        hook_set_vfsflags);
 
index 54b12f42ae54b3d99c23b9c1c13e8160b8bd29ee..8304d3af0ecf603f55ad14aba8cace3db39eec64 100644 (file)
@@ -530,7 +530,7 @@ enum {
 
 extern int mnt_optlist_get_flags(struct libmnt_optlist *ls, unsigned long *flags,
                           const struct libmnt_optmap *map, unsigned int what);
-extern int mnt_optlist_get_attrs(struct libmnt_optlist *ls, uint64_t *attrs);
+extern int mnt_optlist_get_attrs(struct libmnt_optlist *ls, uint64_t *set, uint64_t *clr);
 extern int mnt_optlist_get_optstr(struct libmnt_optlist *ol, const char **optstr,
                         const struct libmnt_optmap *map, unsigned int what);
 extern int mnt_optlist_strdup_optstr(struct libmnt_optlist *ls, char **optstr,
index 6531d5b46e8e5a2e78fee083c45be6d8da3cb4be..939473dc56651c3ac625ebfb850c0873b252326f 100644 (file)
@@ -746,39 +746,65 @@ int mnt_optlist_get_flags(struct libmnt_optlist *ls, unsigned long *flags,
        return 0;
 }
 
-/*
- * Like mnt_optlist_get_flags() for VFS flags, but converts classic MS_* flags to
- * new MOUNT_ATTR_*
- */
-int mnt_optlist_get_attrs(struct libmnt_optlist *ls, uint64_t *attrs)
-{
 #ifdef UL_HAVE_MOUNT_API
-       int rc;
-       unsigned long flags = 0;
-
-       assert(ls);
-       assert(ls->linux_map);
-
-       rc = mnt_optlist_get_flags(ls, &flags, ls->linux_map, 0);
-       if (rc)
-               return rc;
+static inline uint64_t flags_to_attrs(unsigned long flags)
+{
+       uint64_t attrs = 0;
 
        if (flags & MS_RDONLY)
-               *attrs |= MOUNT_ATTR_RDONLY;
+               attrs |= MOUNT_ATTR_RDONLY;
        if (flags & MS_NOSUID)
-               *attrs |= MOUNT_ATTR_NOSUID;
+               attrs |= MOUNT_ATTR_NOSUID;
        if (flags & MS_NOEXEC)
-               *attrs |= MOUNT_ATTR_NOEXEC;
+               attrs |= MOUNT_ATTR_NOEXEC;
        if (flags & MS_NODIRATIME)
-               *attrs |= MOUNT_ATTR_NODIRATIME;
+               attrs |= MOUNT_ATTR_NODIRATIME;
        if (flags & MS_RELATIME)
-               *attrs |= MOUNT_ATTR_RELATIME;
+               attrs |= MOUNT_ATTR_RELATIME;
        if (flags & MS_NOATIME)
-               *attrs |= MOUNT_ATTR_NOATIME;
+               attrs |= MOUNT_ATTR_NOATIME;
        if (flags & MS_STRICTATIME)
-               *attrs |= MOUNT_ATTR_STRICTATIME;
+               attrs |= MOUNT_ATTR_STRICTATIME;
        if (flags & MS_NOSYMFOLLOW)
-               *attrs |= MOUNT_ATTR_NOSYMFOLLOW;
+               attrs |= MOUNT_ATTR_NOSYMFOLLOW;
+
+       return attrs;
+}
+#endif
+
+/*
+ * Like mnt_optlist_get_flags() for VFS flags, but converts classic MS_* flags to
+ * new MOUNT_ATTR_*
+ */
+int mnt_optlist_get_attrs(struct libmnt_optlist *ls, uint64_t *set, uint64_t *clr)
+{
+#ifdef UL_HAVE_MOUNT_API
+       struct libmnt_iter itr;
+       struct libmnt_opt *opt;
+
+       if (!ls || !ls->linux_map || !set || !clr)
+               return -EINVAL;
+
+       mnt_reset_iter(&itr, MNT_ITER_FORWARD);
+
+       while (mnt_optlist_next_opt(ls, &itr, &opt) == 0) {
+               if (ls->linux_map != opt->map)
+                       continue;
+               if (!opt->ent || !opt->ent->id)
+                       continue;
+               if (!is_wanted_opt(opt, ls->linux_map, MNT_OL_FLTR_DFLT))
+                       continue;
+
+               if (opt->ent->mask & MNT_INVERT)
+                       *clr |= flags_to_attrs( opt->ent->id );
+               else
+                       *set |= flags_to_attrs( opt->ent->id );
+       }
+
+       DBG(OPTLIST, ul_debugobj(ls, "return attrs set=0x%08" PRIx64
+                                     ", clr=0x08%" PRIx64, *set, *clr));
+       return 0;
+
 #endif
        return 0;
 }