Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 31d40d74 authored by Miklos Szeredi's avatar Miklos Szeredi Committed by Linus Torvalds
Browse files

[PATCH] FUSE: add access call



Add a new access call, which will only be called if ->permission is invoked
from sys_access().  In all other cases permission checking is delayed until
the actual filesystem operation.

Signed-off-by: default avatarMiklos Szeredi <miklos@szeredi.hu>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 5b62073d
Loading
Loading
Loading
Loading
+35 −0
Original line number Original line Diff line number Diff line
@@ -461,6 +461,38 @@ static int fuse_revalidate(struct dentry *entry)
	return fuse_do_getattr(inode);
	return fuse_do_getattr(inode);
}
}


static int fuse_access(struct inode *inode, int mask)
{
	struct fuse_conn *fc = get_fuse_conn(inode);
	struct fuse_req *req;
	struct fuse_access_in inarg;
	int err;

	if (fc->no_access)
		return 0;

	req = fuse_get_request(fc);
	if (!req)
		return -EINTR;

	memset(&inarg, 0, sizeof(inarg));
	inarg.mask = mask;
	req->in.h.opcode = FUSE_ACCESS;
	req->in.h.nodeid = get_node_id(inode);
	req->inode = inode;
	req->in.numargs = 1;
	req->in.args[0].size = sizeof(inarg);
	req->in.args[0].value = &inarg;
	request_send(fc, req);
	err = req->out.h.error;
	fuse_put_request(fc, req);
	if (err == -ENOSYS) {
		fc->no_access = 1;
		err = 0;
	}
	return err;
}

static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
{
{
	struct fuse_conn *fc = get_fuse_conn(inode);
	struct fuse_conn *fc = get_fuse_conn(inode);
@@ -493,6 +525,9 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
		int mode = inode->i_mode;
		int mode = inode->i_mode;
		if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO))
		if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO))
			return -EACCES;
			return -EACCES;

		if (nd && (nd->flags & LOOKUP_ACCESS))
			return fuse_access(inode, mask);
		return 0;
		return 0;
	}
	}
}
}
+3 −0
Original line number Original line Diff line number Diff line
@@ -266,6 +266,9 @@ struct fuse_conn {
	/** Is removexattr not implemented by fs? */
	/** Is removexattr not implemented by fs? */
	unsigned no_removexattr : 1;
	unsigned no_removexattr : 1;


	/** Is access not implemented by fs? */
	unsigned no_access : 1;

	/** Backing dev info */
	/** Backing dev info */
	struct backing_dev_info bdi;
	struct backing_dev_info bdi;
};
};
+7 −1
Original line number Original line Diff line number Diff line
@@ -99,7 +99,8 @@ enum fuse_opcode {
	FUSE_OPENDIR       = 27,
	FUSE_OPENDIR       = 27,
	FUSE_READDIR       = 28,
	FUSE_READDIR       = 28,
	FUSE_RELEASEDIR    = 29,
	FUSE_RELEASEDIR    = 29,
	FUSE_FSYNCDIR      = 30
	FUSE_FSYNCDIR      = 30,
	FUSE_ACCESS        = 34
};
};


/* Conservative buffer size for the client */
/* Conservative buffer size for the client */
@@ -222,6 +223,11 @@ struct fuse_getxattr_out {
	__u32	padding;
	__u32	padding;
};
};


struct fuse_access_in {
	__u32	mask;
	__u32	padding;
};

struct fuse_init_in_out {
struct fuse_init_in_out {
	__u32	major;
	__u32	major;
	__u32	minor;
	__u32	minor;