high-level: add fmask and dmask options
authorgandalfs_cat <meow@kittcat.dev>
Sun, 23 Jun 2024 11:28:30 +0000 (04:28 -0700)
committerBernd Schubert <bernd.schubert@fastmail.fm>
Wed, 3 Jul 2024 10:50:06 +0000 (12:50 +0200)
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
include/fuse.h
lib/fuse.c

index 230c6affcae8d5edff8b82bef49e6a57b6b3ea65..32862fcceefd5d53af1b3190427e1260999d47ad 100644 (file)
@@ -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).
index a3549cb19e3bd06e45fd905c4e109bd574cbbb07..ad50d7f777171c82d6b0a3859e357c94214b8e82 100644 (file)
@@ -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;
 };
 
 
index 35a807b939a9d6324132b00493cd16134c7f83a9..24b843f82226f0feb23940ee4a720fa976c39e5f 100644 (file)
@@ -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"