From 189a1bf3b314a8fc48c29ea1e0287d5cc71021a0 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 16 Jan 2019 15:00:07 +0100 Subject: libmount: add support for MS_REMOUNT on --all This patch add to support for remount-all operation to libmount and mount(8). For example: mount --all -o remount,ro -t vfat to remount read-only all VFAT filesystems. Addresses: https://github.com/karelzak/util-linux/issues/589 Signed-off-by: Karel Zak --- libmount/src/context.c | 43 ++++++++++++++++++ libmount/src/context_mount.c | 106 +++++++++++++++++++++++++++++++++++++++++++ libmount/src/libmount.h.in | 6 +++ libmount/src/libmount.sym | 1 + libmount/src/mountP.h | 1 + 5 files changed, 157 insertions(+) (limited to 'libmount/src') diff --git a/libmount/src/context.c b/libmount/src/context.c index b9c18d94f..af9b9ca50 100644 --- a/libmount/src/context.c +++ b/libmount/src/context.c @@ -193,6 +193,49 @@ int mnt_reset_context(struct libmnt_context *cxt) return 0; } +struct libmnt_context *mnt_copy_context(struct libmnt_context *o) +{ + struct libmnt_context *n; + + n = mnt_new_context(); + if (!n) + return NULL; + + DBG(CXT, ul_debugobj(n, "<---- clone ---->")); + + n->flags = o->flags; + + if (o->fs) { + n->fs = mnt_copy_fs(NULL, o->fs); + if (!n->fs) + goto failed; + } + + n->mtab = o->mtab; + mnt_ref_table(n->mtab); + + n->mtab = o->utab; + mnt_ref_table(n->utab); + + if (o->helper) + n->helper = strdup(o->helper); + if (o->orig_user) + n->orig_user = strdup(o->orig_user); + + n->mountflags = o->mountflags; + n->mountdata = o->mountdata; + + mnt_context_reset_status(n); + + n->table_fltrcb = o->table_fltrcb; + n->table_fltrcb_data = o->table_fltrcb_data; + + return n; +failed: + mnt_free_context(n); + return NULL; +} + /** * mnt_context_reset_status: * @cxt: context diff --git a/libmount/src/context_mount.c b/libmount/src/context_mount.c index f914c9b1b..307da3c5c 100644 --- a/libmount/src/context_mount.c +++ b/libmount/src/context_mount.c @@ -1382,6 +1382,112 @@ int mnt_context_next_mount(struct libmnt_context *cxt, return 0; } + +/** + * mnt_context_next_remount: + * @cxt: context + * @itr: iterator + * @fs: returns the current filesystem + * @mntrc: returns the return code from mnt_context_mount() + * @ignored: returns 1 for non-matching + * + * This function tries to remount the next mounted filesystem (as returned by + * mnt_context_get_mtab()). + * + * You can filter out filesystems by: + * mnt_context_set_options_pattern() to simulate mount -a -O pattern + * mnt_context_set_fstype_pattern() to simulate mount -a -t pattern + * + * If the filesystem does not match defined criteria, then the + * mnt_context_next_remount() function returns zero, but the @ignored is + * non-zero. + * + * If mount(2) syscall or mount.type helper failed, then the + * mnt_context_renext_mount() function returns zero, but the @mntrc is non-zero. + * Use also mnt_context_get_status() to check if the filesystem was + * successfully mounted. + * + * See mnt_context_mount() for more details about errors and warnings. + * + * Returns: 0 on success, + * <0 in case of error (!= mount(2) errors) + * 1 at the end of the list. + */ +int mnt_context_next_remount(struct libmnt_context *cxt, + struct libmnt_iter *itr, + struct libmnt_fs **fs, + int *mntrc, + int *ignored) +{ + struct libmnt_context *remount_cxt = NULL; + struct libmnt_table *mtab; + const char *tgt; + int rc; + + if (ignored) + *ignored = 0; + if (mntrc) + *mntrc = 0; + + if (!cxt || !fs || !itr) + return -EINVAL; + + rc = mnt_context_get_mtab(cxt, &mtab); + if (rc) + return rc; + + rc = mnt_table_next_fs(mtab, itr, fs); + if (rc != 0) + return rc; /* more filesystems (or error) */ + + tgt = mnt_fs_get_target(*fs); + + DBG(CXT, ul_debugobj(cxt, "next-remount: trying %s", tgt)); + + /* ignore filesystems which don't match options patterns */ + if ((cxt->fstype_pattern && !mnt_fs_match_fstype(*fs, + cxt->fstype_pattern)) || + + /* ignore filesystems which don't match type patterns */ + (cxt->optstr_pattern && !mnt_fs_match_options(*fs, + cxt->optstr_pattern))) { + if (ignored) + *ignored = 1; + DBG(CXT, ul_debugobj(cxt, "next-remount: not-match " + "[fstype: %s, t-pattern: %s, options: %s, O-pattern: %s]", + mnt_fs_get_fstype(*fs), + cxt->fstype_pattern, + mnt_fs_get_options(*fs), + cxt->optstr_pattern)); + return 0; + } + + /* make sure fstab is already read to avoid fstab parsing in cloned context */ + mnt_context_get_fstab(cxt, NULL); + + /* clone context */ + remount_cxt = mnt_copy_context(cxt); + if (!remount_cxt) + return -ENOMEM; + + rc = mnt_context_set_target(remount_cxt, tgt); + if (!rc) { + /* + * "-t " is used to filter out fstab entries, but for ordinary + * mount operation -t means "-t ". We have to zeroize the pattern + * to avoid misinterpretation. + */ + remount_cxt->fstype_pattern = NULL; + rc = mnt_context_mount(remount_cxt); + + if (mntrc) + *mntrc = rc; + } + + mnt_free_context(remount_cxt); + return 0; +} + /* * Returns 1 if @dir parent is shared */ diff --git a/libmount/src/libmount.h.in b/libmount/src/libmount.h.in index 1ce9995ec..a14bb6f3d 100644 --- a/libmount/src/libmount.h.in +++ b/libmount/src/libmount.h.in @@ -849,6 +849,12 @@ extern int mnt_context_next_mount(struct libmnt_context *cxt, struct libmnt_fs **fs, int *mntrc, int *ignored); +extern int mnt_context_next_remount(struct libmnt_context *cxt, + struct libmnt_iter *itr, + struct libmnt_fs **fs, + int *mntrc, + int *ignored); + extern int mnt_context_prepare_mount(struct libmnt_context *cxt) __ul_attribute__((warn_unused_result)); extern int mnt_context_do_mount(struct libmnt_context *cxt); diff --git a/libmount/src/libmount.sym b/libmount/src/libmount.sym index 5145c876d..0087a3d23 100644 --- a/libmount/src/libmount.sym +++ b/libmount/src/libmount.sym @@ -344,4 +344,5 @@ MOUNT_2.33 { MOUNT_2.34 { mnt_guess_system_root; + mnt_context_next_remount; } MOUNT_2.33; diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h index 795ea69dc..7887c0a55 100644 --- a/libmount/src/mountP.h +++ b/libmount/src/mountP.h @@ -403,6 +403,7 @@ extern int __mnt_fs_set_fstype_ptr(struct libmnt_fs *fs, char *fstype) __attribute__((nonnull(1))); /* context.c */ +extern struct libmnt_context *mnt_copy_context(struct libmnt_context *o); extern int mnt_context_mtab_writable(struct libmnt_context *cxt); extern int mnt_context_utab_writable(struct libmnt_context *cxt); extern const char *mnt_context_get_writable_tabpath(struct libmnt_context *cxt); -- cgit v1.2.3-55-g7522