aboutsummaryrefslogtreecommitdiffstats
path: root/util/fusermount.c
diff options
context:
space:
mode:
authorMatthew <matthew@matthew-cash.com>2024-02-23 22:56:49 -0800
committerGitHub <noreply@github.com>2024-02-24 07:56:49 +0100
commit74b1df2e84e836a1710561f52075d51f20cd5c78 (patch)
treef1cdbbe566e18dc5d0ac86b237bf935c8de2acaa /util/fusermount.c
parent402c8fff588120a7cf5922822904ce45f30612a8 (diff)
downloadlibfuse-74b1df2e84e836a1710561f52075d51f20cd5c78.tar.gz
Passthrough options starting with "x-" to mtab (#894)
This implements #651, tested with bindfs. "x-*" options are comments meant to be interpreted by userspace. #651 is about some 3rd party mount options like 'x-gvfs-notrash'. This also removes the test if /etc/mtab is a symlink. This test was added in commit 5f28cd15ab43c741f6d116be4d3a9aa5d82ab385 and the corresponding ChangeLog entry in this commit points to mount issues for read-only mtab. However, in all recent Linux distributions /etc/mtab is a symlink to /proc/self/mounts and never writable. In fact, util-linux 2.39 (libmount) entirely removed support for a writable mtab. At least since util-linux 2.19 (10-Feb-2011) /run/mount/utab is used as replacement for userspace mount entries..
Diffstat (limited to 'util/fusermount.c')
-rw-r--r--util/fusermount.c50
1 files changed, 48 insertions, 2 deletions
diff --git a/util/fusermount.c b/util/fusermount.c
index a2dd8e1..fe75631 100644
--- a/util/fusermount.c
+++ b/util/fusermount.c
@@ -97,6 +97,30 @@ static struct mntent *GETMNTENT(FILE *stream)
#define GETMNTENT getmntent
#endif // GETMNTENT_NEEDS_UNESCAPING
+/*
+ * Take a ',' separated option string and extract "x-" options
+ */
+static void extract_x_options(const char *original, char *non_x_opts, char *x_opts)
+{
+ size_t len;
+ const char *opt, *opt_end;
+ char *opt_buf;
+
+ len = strlen(original);
+
+ for (opt = original; opt < original + len; opt = opt_end + 1) {
+ opt_end = strchr(opt, ',');
+ if (opt_end == NULL)
+ opt_end = original + len;
+
+ opt_buf = strncmp(opt, "x-", 2) ? non_x_opts : x_opts;
+
+ if (strlen(opt_buf) > 1)
+ strncat(opt_buf, ",", 2);
+
+ strncat(opt_buf, opt, opt_end - opt);
+ }
+}
static const char *get_user_name(void)
{
@@ -1135,6 +1159,11 @@ static int mount_fuse(const char *mnt, const char *opts, const char **type)
char *mnt_opts = NULL;
const char *real_mnt = mnt;
int mountpoint_fd = -1;
+ size_t opts_size;
+ char *do_mount_opts;
+ char *x_opts;
+ size_t add_mount_opts_size, add_mount_opts_len;
+ char *add_mount_opts;
fd = open_fuse_device(&dev);
if (fd == -1)
@@ -1151,11 +1180,17 @@ static int mount_fuse(const char *mnt, const char *opts, const char **type)
}
}
+ // Extract any options starting with "x-"
+ opts_size = strlen(opts) + 1;
+ do_mount_opts = malloc(opts_size);
+ x_opts = malloc(opts_size);
+ extract_x_options(opts, do_mount_opts, x_opts);
+
res = check_perm(&real_mnt, &stbuf, &mountpoint_fd);
restore_privs();
if (res != -1)
res = do_mount(real_mnt, type, stbuf.st_mode & S_IFMT,
- fd, opts, dev, &source, &mnt_opts);
+ fd, do_mount_opts, dev, &source, &mnt_opts);
if (mountpoint_fd != -1)
close(mountpoint_fd);
@@ -1170,7 +1205,18 @@ static int mount_fuse(const char *mnt, const char *opts, const char **type)
}
if (geteuid() == 0) {
- res = add_mount(source, mnt, *type, mnt_opts);
+ // Add back the options starting with "x-" to opts from do_mount
+ add_mount_opts_size = strlen(mnt_opts) + strlen(x_opts) + 2;
+ add_mount_opts = malloc(add_mount_opts_size);
+
+ strncpy(add_mount_opts, mnt_opts, add_mount_opts_size - 1);
+ add_mount_opts_len = strlen(add_mount_opts);
+ if (add_mount_opts_len > 0)
+ strncat(add_mount_opts, ",", 2);
+ strncat(add_mount_opts, x_opts,
+ add_mount_opts_size - add_mount_opts_len - 2);
+
+ res = add_mount(source, mnt, *type, add_mount_opts);
if (res == -1) {
/* Can't clean up mount in a non-racy way */
goto fail_close_fd;