[prev in list] [next in list] [prev in thread] [next in thread] 

List:       fuse-devel
Subject:    [fuse-devel] [PATCH] libfuse: allow umask processing in userspace
From:       Miklos Szeredi <miklos () szeredi ! hu>
Date:       2009-06-23 10:23:56
Message-ID: E1MJ3AS-00077O-8Y () pomaz-ex ! szeredi ! hu
[Download RAW message or body]

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@FUSE_2.4");
+
+
 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 {

------------------------------------------------------------------------------
Are you an open source citizen? Join us for the Open Source Bridge conference!
Portland, OR, June 17-19. Two days of sessions, one day of unconference: $250.
Need another reason to go? 24-hour hacker lounge. Register today!
http://ad.doubleclick.net/clk;215844324;13503038;v?http://opensourcebridge.org
_______________________________________________
fuse-devel mailing list
fuse-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/fuse-devel
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic