From: Karel Zak Date: Thu, 22 Sep 2022 09:05:53 +0000 (+0200) Subject: libmount: support VFS flags attributes clear X-Git-Tag: v2.39-rc1~253 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ddebca17498f485c70bcba2f3f5dcec4a27aa99d;p=thirdparty%2Futil-linux.git libmount: support VFS flags attributes clear Signed-off-by: Karel Zak --- diff --git a/libmount/src/hook_mount.c b/libmount/src/hook_mount.c index d4be4d7370..abfd00ebf7 100644 --- a/libmount/src/hook_mount.c +++ b/libmount/src/hook_mount.c @@ -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); diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h index 54b12f42ae..8304d3af0e 100644 --- a/libmount/src/mountP.h +++ b/libmount/src/mountP.h @@ -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, diff --git a/libmount/src/optlist.c b/libmount/src/optlist.c index 6531d5b46e..939473dc56 100644 --- a/libmount/src/optlist.c +++ b/libmount/src/optlist.c @@ -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; }