This patch against fuse-2.8.0-pre3 lets filesystems handle masking the file mode on creation. fuse_ctx (lowlevel API) and fuse_context (high level API) are extended with a 'umask' field. If the kernel doesn't send the umask, it is set to zero. Introduce a new feature flag FUSE_CAP_DONT_MASK, if the kernel supports this feature, then this flag will be set in conn->capable in the ->init() method. If the filesystem sets this flag in in conn->want, then the create modes will not be masked. Testing is welcome. Thanks, Miklos --- include/fuse.h | 3 +++ include/fuse_common.h | 2 ++ include/fuse_kernel.h | 20 ++++++++++++++++++-- include/fuse_lowlevel.h | 3 +++ lib/fuse_lowlevel.c | 38 +++++++++++++++++++++++++++++++++++--- lib/fuse_versionscript | 4 ++-- 6 files changed, 63 insertions(+), 7 deletions(-) Index: fuse/include/fuse_lowlevel.h =================================================================== --- fuse.orig/include/fuse_lowlevel.h 2009-06-23 09:57:22.000000000 +0200 +++ fuse/include/fuse_lowlevel.h 2009-06-23 09:58:14.000000000 +0200 @@ -109,6 +109,9 @@ struct fuse_ctx { /** Thread ID of the calling process */ pid_t pid; + + /** Umask of the calling process (introduced in version 2.8) */ + mode_t umask; }; /* 'to_set' flags in setattr */ Index: fuse/lib/fuse_lowlevel.c =================================================================== --- fuse.orig/lib/fuse_lowlevel.c 2009-06-23 09:57:22.000000000 +0200 +++ fuse/lib/fuse_lowlevel.c 2009-06-23 10:07:21.000000000 +0200 @@ -606,9 +606,15 @@ static void do_readlink(fuse_req_t req, static void do_mknod(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { struct fuse_mknod_in *arg = (struct fuse_mknod_in *) inarg; + char *name = PARAM(arg); + + if (req->f->conn.proto_minor >= 12) + req->ctx.umask = arg->umask; + else + name = (char *) inarg + FUSE_COMPAT_MKNOD_IN_SIZE; if (req->f->op.mknod) - req->f->op.mknod(req, nodeid, PARAM(arg), arg->mode, arg->rdev); + req->f->op.mknod(req, nodeid, name, arg->mode, arg->rdev); else fuse_reply_err(req, ENOSYS); } @@ -617,6 +623,9 @@ static void do_mkdir(fuse_req_t req, fus { struct fuse_mkdir_in *arg = (struct fuse_mkdir_in *) inarg; + if (req->f->conn.proto_minor >= 12) + req->ctx.umask = arg->umask; + if (req->f->op.mkdir) req->f->op.mkdir(req, nodeid, PARAM(arg), arg->mode); else @@ -678,15 +687,21 @@ static void do_link(fuse_req_t req, fuse static void do_create(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - struct fuse_open_in *arg = (struct fuse_open_in *) inarg; + struct fuse_create_in *arg = (struct fuse_create_in *) inarg; if (req->f->op.create) { struct fuse_file_info fi; + char *name = PARAM(arg); memset(&fi, 0, sizeof(fi)); fi.flags = arg->flags; - req->f->op.create(req, nodeid, PARAM(arg), arg->mode, &fi); + if (req->f->conn.proto_minor >= 12) + req->ctx.umask = arg->umask; + else + name = (char *) inarg + sizeof(struct fuse_open_in); + + req->f->op.create(req, nodeid, name, arg->mode, &fi); } else fuse_reply_err(req, ENOSYS); } @@ -1168,6 +1183,8 @@ static void do_init(fuse_req_t req, fuse f->conn.capable |= FUSE_CAP_EXPORT_SUPPORT; if (arg->flags & FUSE_BIG_WRITES) f->conn.capable |= FUSE_CAP_BIG_WRITES; + if (arg->flags & FUSE_DONT_MASK) + f->conn.capable |= FUSE_CAP_DONT_MASK; } else { f->conn.async_read = 0; f->conn.max_readahead = 0; @@ -1207,6 +1224,8 @@ static void do_init(fuse_req_t req, fuse outarg.flags |= FUSE_EXPORT_SUPPORT; if (f->conn.want & FUSE_CAP_BIG_WRITES) outarg.flags |= FUSE_BIG_WRITES; + if (f->conn.want & FUSE_CAP_DONT_MASK) + outarg.flags |= FUSE_DONT_MASK; outarg.max_readahead = f->conn.max_readahead; outarg.max_write = f->conn.max_write; @@ -1280,6 +1299,19 @@ const struct fuse_ctx *fuse_req_ctx(fuse return &req->ctx; } +/* + * The size of fuse_ctx got extended, so need to be careful about + * incompatibility (i.e. a new binary cannot work with an old + * library). + */ +const struct fuse_ctx *fuse_req_ctx_compat24(fuse_req_t req); +const struct fuse_ctx *fuse_req_ctx_compat24(fuse_req_t req) +{ + return fuse_req_ctx(req); +} +FUSE_SYMVER(".symver fuse_req_ctx_compat24,fuse_req_ctx@xxxxxxxx"); + + void fuse_req_interrupt_func(fuse_req_t req, fuse_interrupt_func_t func, void *data) { Index: fuse/lib/fuse_versionscript =================================================================== --- fuse.orig/lib/fuse_versionscript 2009-06-23 09:57:22.000000000 +0200 +++ fuse/lib/fuse_versionscript 2009-06-23 09:58:14.000000000 +0200 @@ -3,7 +3,6 @@ FUSE_2.2 { fuse_destroy; fuse_exit; fuse_exited; - fuse_get_context; fuse_invalidate; fuse_is_lib_option; fuse_loop; @@ -43,7 +42,6 @@ FUSE_2.4 { fuse_reply_readlink; fuse_reply_write; fuse_reply_xattr; - fuse_req_ctx; fuse_req_userdata; fuse_session_add_chan; fuse_session_destroy; @@ -176,6 +174,8 @@ FUSE_2.8 { fuse_reply_poll; fuse_req_getgroups; fuse_getgroups; + fuse_req_ctx; + fuse_get_context; local: *; Index: fuse/include/fuse.h =================================================================== --- fuse.orig/include/fuse.h 2009-06-23 09:57:22.000000000 +0200 +++ fuse/include/fuse.h 2009-06-23 09:58:14.000000000 +0200 @@ -518,6 +518,9 @@ struct fuse_context { /** Private filesystem data */ void *private_data; + + /** Umask of the calling process (introduced in version 2.8) */ + mode_t umask; }; /** Index: fuse/include/fuse_common.h =================================================================== --- fuse.orig/include/fuse_common.h 2009-06-23 09:57:22.000000000 +0200 +++ fuse/include/fuse_common.h 2009-06-23 09:58:14.000000000 +0200 @@ -88,12 +88,14 @@ struct fuse_file_info { * FUSE_CAP_ATOMIC_O_TRUNC: filesystem handles the O_TRUNC open flag * FUSE_CAP_EXPORT_SUPPORT: filesystem handles lookups of "." and ".." * FUSE_CAP_BIG_WRITES: filesystem can handle write size larger than 4kB + * FUSE_CAP_DONT_MASK: don't apply umask to file mode on create operations */ #define FUSE_CAP_ASYNC_READ (1 << 0) #define FUSE_CAP_POSIX_LOCKS (1 << 1) #define FUSE_CAP_ATOMIC_O_TRUNC (1 << 3) #define FUSE_CAP_EXPORT_SUPPORT (1 << 4) #define FUSE_CAP_BIG_WRITES (1 << 5) +#define FUSE_CAP_DONT_MASK (1 << 6) /** * Ioctl flags Index: fuse/include/fuse_kernel.h =================================================================== --- fuse.orig/include/fuse_kernel.h 2009-06-23 09:57:22.000000000 +0200 +++ fuse/include/fuse_kernel.h 2009-06-23 10:06:10.000000000 +0200 @@ -51,6 +51,9 @@ * - add IOCTL message * - add unsolicited notification support * - add POLL message and NOTIFY_POLL notification + * + * 7.12 + * - add umask flag to input argument of open, mknod and mkdir */ #ifndef _LINUX_FUSE_H @@ -65,7 +68,7 @@ #define FUSE_KERNEL_VERSION 7 /** Minor version number of this interface */ -#define FUSE_KERNEL_MINOR_VERSION 11 +#define FUSE_KERNEL_MINOR_VERSION 12 /** The node ID of the root inode */ #define FUSE_ROOT_ID 1 @@ -141,6 +144,7 @@ struct fuse_file_lock { * INIT request/reply flags * * FUSE_EXPORT_SUPPORT: filesystem handles lookups of "." and ".." + * FUSE_DONT_MASK: don't apply umask to file mode on create operations */ #define FUSE_ASYNC_READ (1 << 0) #define FUSE_POSIX_LOCKS (1 << 1) @@ -148,6 +152,7 @@ struct fuse_file_lock { #define FUSE_ATOMIC_O_TRUNC (1 << 3) #define FUSE_EXPORT_SUPPORT (1 << 4) #define FUSE_BIG_WRITES (1 << 5) +#define FUSE_DONT_MASK (1 << 6) /** * CUSE INIT request/reply flags @@ -291,14 +296,18 @@ struct fuse_attr_out { struct fuse_attr attr; }; +#define FUSE_COMPAT_MKNOD_IN_SIZE 8 + struct fuse_mknod_in { __u32 mode; __u32 rdev; + __u32 umask; + __u32 padding; }; struct fuse_mkdir_in { __u32 mode; - __u32 padding; + __u32 umask; }; struct fuse_rename_in { @@ -330,7 +339,14 @@ struct fuse_setattr_in { struct fuse_open_in { __u32 flags; + __u32 unused; +}; + +struct fuse_create_in { + __u32 flags; __u32 mode; + __u32 umask; + __u32 padding; }; struct fuse_open_out { -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html