From 54b8cd6757ed383c0da10a5ba6a778dd45f28ad6 Mon Sep 17 00:00:00 2001 From: gandalfs_cat Date: Sun, 23 Jun 2024 04:28:30 -0700 Subject: [PATCH] high-level: add fmask and dmask options dmask: umask applied to directories fmask: umask applied to non-directories to get "typical" permission bits for regular files (0644) and directories (0755), a single umask option is not sufficient (or well, it isn't the way fuse implements it) there is precident for separate umask and dmask options in other filesystems (see for example fat: https://github.com/torvalds/linux/tree/master/fs/fat) this addition should not affect backward-compatibility; the original umask option retains the same meaning, but non-zero fmask or dmask will override it. --- doc/mount.fuse3.8 | 4 ++-- include/fuse.h | 8 ++++++++ lib/fuse.c | 20 +++++++++++++++++--- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/doc/mount.fuse3.8 b/doc/mount.fuse3.8 index 230c6af..32862fc 100644 --- a/doc/mount.fuse3.8 +++ b/doc/mount.fuse3.8 @@ -181,8 +181,8 @@ This option is an alternative to cached data is invalidated on \fBopen\fP(2) if the modification time or the size of the file has changed since it was last opened. .TP -\fBumask=M\fP -Override the permission bits in \fIst_mode\fP set by the filesystem. The resulting permission bits are the ones missing from the given umask value. The value is given in octal representation. +\fBumask=M fmask=M dmask=M\fP +Override the permission bits set by the filesystem in \fIst_mode\fP. The resulting permission bits are the ones missing from the mask value, which is given in octal representation. \fBfmask\fP and \fBdmask\fP (respectively) may be used to control the permission bits of files and directories separately. umask is overridden by the individual fmask and dmask options. .TP \fBuid=N\fP Override the \fIst_uid\fP field set by the filesystem (N is numeric). diff --git a/include/fuse.h b/include/fuse.h index a3549cb..ad50d7f 100644 --- a/include/fuse.h +++ b/include/fuse.h @@ -298,6 +298,14 @@ struct fuse_config { int show_help; char *modules; int debug; + + /** + * `fmask` and `dmask` function the same way as `umask`, but apply + * to files and directories separately. If non-zero, `fmask` and + * `dmask` take precedence over the `umask` setting. + */ + unsigned int fmask; + unsigned int dmask; }; diff --git a/lib/fuse.c b/lib/fuse.c index 35a807b..24b843f 100644 --- a/lib/fuse.c +++ b/lib/fuse.c @@ -1487,9 +1487,17 @@ static void set_stat(struct fuse *f, fuse_ino_t nodeid, struct stat *stbuf) { if (!f->conf.use_ino) stbuf->st_ino = nodeid; - if (f->conf.set_mode) - stbuf->st_mode = (stbuf->st_mode & S_IFMT) | - (0777 & ~f->conf.umask); + if (f->conf.set_mode) { + if (f->conf.dmask && S_ISDIR(stbuf->st_mode)) + stbuf->st_mode = (stbuf->st_mode & S_IFMT) | + (0777 & ~f->conf.dmask); + else if (f->conf.fmask) + stbuf->st_mode = (stbuf->st_mode & S_IFMT) | + (0777 & ~f->conf.fmask); + else + stbuf->st_mode = (stbuf->st_mode & S_IFMT) | + (0777 & ~f->conf.umask); + } if (f->conf.set_uid) stbuf->st_uid = f->conf.uid; if (f->conf.set_gid) @@ -4681,6 +4689,10 @@ static const struct fuse_opt fuse_lib_opts[] = { FUSE_LIB_OPT("no_rofd_flush", no_rofd_flush, 1), FUSE_LIB_OPT("umask=", set_mode, 1), FUSE_LIB_OPT("umask=%o", umask, 0), + FUSE_LIB_OPT("fmask=", set_mode, 1), + FUSE_LIB_OPT("fmask=%o", fmask, 0), + FUSE_LIB_OPT("dmask=", set_mode, 1), + FUSE_LIB_OPT("dmask=%o", dmask, 0), FUSE_LIB_OPT("uid=", set_uid, 1), FUSE_LIB_OPT("uid=%d", uid, 0), FUSE_LIB_OPT("gid=", set_gid, 1), @@ -4734,6 +4746,8 @@ void fuse_lib_help(struct fuse_args *args) " -o [no]auto_cache enable caching based on modification times (off)\n" " -o no_rofd_flush disable flushing of read-only fd on close (off)\n" " -o umask=M set file permissions (octal)\n" +" -o fmask=M set file permissions (octal)\n" +" -o dmask=M set dir permissions (octal)\n" " -o uid=N set file owner\n" " -o gid=N set file group\n" " -o entry_timeout=T cache timeout for names (1.0s)\n" -- 2.30.2