mirror of
https://github.com/libfuse/libfuse.git
synced 2024-11-28 14:44:35 +08:00
fix
This commit is contained in:
parent
e77cc07e75
commit
7b28eaeac5
@ -12,6 +12,9 @@
|
||||
userspace. For both mount options, if the option is given, then
|
||||
the respective open flag is set, otherwise the open flag is left
|
||||
unmodified (so the filesystem can set it).
|
||||
|
||||
* Add ACCESS operation. This is called from the access() system
|
||||
call if 'default_permissions' mount option is not given
|
||||
|
||||
2005-07-28 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
|
@ -306,6 +306,17 @@ struct fuse_operations {
|
||||
* Introduced in version 2.3
|
||||
*/
|
||||
void (*destroy) (void *);
|
||||
|
||||
/**
|
||||
* Check file access permissions
|
||||
*
|
||||
* Need not be implemented. Will only be called for the access()
|
||||
* system call, and only if 'default_permissions' mount option is
|
||||
* not given.
|
||||
*
|
||||
* Introduced in version 2.4
|
||||
*/
|
||||
int (*access) (const char *, int);
|
||||
};
|
||||
|
||||
/** Extra context that may be needed by some filesystems
|
||||
|
@ -26,11 +26,12 @@ struct fuse_file_info {
|
||||
writepage */
|
||||
int writepage;
|
||||
|
||||
/** Can be filled in by open, to use direct I/O on this file */
|
||||
/** Can be filled in by open, to use direct I/O on this file.
|
||||
Introduced in version 2.4 */
|
||||
unsigned int direct_io : 1;
|
||||
|
||||
/** Can be filled in by open, to indicate, that cached file data
|
||||
need not be invalidated */
|
||||
need not be invalidated. Introduced in version 2.4 */
|
||||
unsigned int keep_cache : 1;
|
||||
};
|
||||
|
||||
|
@ -78,6 +78,7 @@ struct fuse_ll_operations {
|
||||
void (*getattr)(fuse_req_t req, fuse_ino_t ino);
|
||||
void (*setattr)(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
|
||||
int to_set);
|
||||
void (*access) (fuse_req_t req, fuse_ino_t ino, int mask);
|
||||
void (*readlink)(fuse_req_t req, fuse_ino_t ino);
|
||||
void (*mknod) (fuse_req_t req, fuse_ino_t parent, const char *name,
|
||||
mode_t mode, dev_t rdev);
|
||||
|
45
kernel/dir.c
45
kernel/dir.c
@ -476,17 +476,50 @@ static int fuse_revalidate(struct dentry *entry)
|
||||
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)
|
||||
{
|
||||
struct fuse_conn *fc = get_fuse_conn(inode);
|
||||
int err;
|
||||
|
||||
if (!fuse_allow_task(fc, current))
|
||||
return -EACCES;
|
||||
else if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
|
||||
#ifdef KERNEL_2_6_10_PLUS
|
||||
int err = generic_permission(inode, mask, NULL);
|
||||
err = generic_permission(inode, mask, NULL);
|
||||
#else
|
||||
int err = vfs_permission(inode, mask);
|
||||
err = vfs_permission(inode, mask);
|
||||
#endif
|
||||
|
||||
/* If permission is denied, try to refresh file
|
||||
@ -510,8 +543,6 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
|
||||
This is actually not so grave, since the user can
|
||||
simply keep access to the file/directory anyway by
|
||||
keeping it open... */
|
||||
|
||||
return err;
|
||||
} else {
|
||||
int mode = inode->i_mode;
|
||||
if ((mask & MAY_WRITE) && IS_RDONLY(inode) &&
|
||||
@ -519,8 +550,12 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
|
||||
return -EROFS;
|
||||
if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO))
|
||||
return -EACCES;
|
||||
return 0;
|
||||
|
||||
err = 0;
|
||||
if (nd->flags & LOOKUP_ACCESS)
|
||||
err = fuse_access(inode, mask);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
|
||||
|
@ -334,9 +334,12 @@ struct fuse_conn {
|
||||
/** Is removexattr not implemented by fs? */
|
||||
unsigned no_removexattr : 1;
|
||||
|
||||
/** Are file locking primitives implemented by fs? */
|
||||
/** Are file locking primitives not implemented by fs? */
|
||||
unsigned no_lk : 1;
|
||||
|
||||
/** Is access not implemented by fs */
|
||||
unsigned no_access : 1;
|
||||
|
||||
#ifdef KERNEL_2_6
|
||||
/** Backing dev info */
|
||||
struct backing_dev_info bdi;
|
||||
|
@ -105,7 +105,8 @@ enum fuse_opcode {
|
||||
FUSE_FSYNCDIR = 30,
|
||||
FUSE_GETLK = 31,
|
||||
FUSE_SETLK = 32,
|
||||
FUSE_SETLKW = 33
|
||||
FUSE_SETLKW = 33,
|
||||
FUSE_ACCESS = 34
|
||||
};
|
||||
|
||||
/* Conservative buffer size for the client */
|
||||
@ -232,6 +233,11 @@ struct fuse_lk_in_out {
|
||||
struct fuse_file_lock lk;
|
||||
};
|
||||
|
||||
struct fuse_access_in {
|
||||
__u32 mask;
|
||||
__u32 padding;
|
||||
};
|
||||
|
||||
struct fuse_init_in_out {
|
||||
__u32 major;
|
||||
__u32 minor;
|
||||
|
20
lib/fuse.c
20
lib/fuse.c
@ -724,6 +724,25 @@ static void fuse_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
|
||||
reply_err(req, err);
|
||||
}
|
||||
|
||||
static void fuse_access(fuse_req_t req, fuse_ino_t ino, int mask)
|
||||
{
|
||||
struct fuse *f = req_fuse_prepare(req);
|
||||
char *path;
|
||||
int err;
|
||||
|
||||
err = -ENOENT;
|
||||
pthread_rwlock_rdlock(&f->tree_lock);
|
||||
path = get_path(f, ino);
|
||||
if (path != NULL) {
|
||||
err = -ENOSYS;
|
||||
if (f->op.access)
|
||||
err = f->op.access(path, mask);
|
||||
free(path);
|
||||
}
|
||||
pthread_rwlock_unlock(&f->tree_lock);
|
||||
reply_err(req, err);
|
||||
}
|
||||
|
||||
static void fuse_readlink(fuse_req_t req, fuse_ino_t ino)
|
||||
{
|
||||
struct fuse *f = req_fuse_prepare(req);
|
||||
@ -1589,6 +1608,7 @@ static struct fuse_ll_operations fuse_path_ops = {
|
||||
.forget = fuse_forget,
|
||||
.getattr = fuse_getattr,
|
||||
.setattr = fuse_setattr,
|
||||
.access = fuse_access,
|
||||
.readlink = fuse_readlink,
|
||||
.mknod = fuse_mknod,
|
||||
.mkdir = fuse_mkdir,
|
||||
|
@ -81,6 +81,7 @@ static const char *opname(enum fuse_opcode opcode)
|
||||
case FUSE_GETLK: return "GETLK";
|
||||
case FUSE_SETLK: return "SETLK";
|
||||
case FUSE_SETLKW: return "SETLKW";
|
||||
case FUSE_ACCESS: return "ACCESS";
|
||||
default: return "???";
|
||||
}
|
||||
}
|
||||
@ -430,6 +431,14 @@ static void do_setattr(fuse_req_t req, fuse_ino_t nodeid,
|
||||
fuse_reply_err(req, ENOSYS);
|
||||
}
|
||||
|
||||
static void do_access(fuse_req_t req, fuse_ino_t nodeid,
|
||||
struct fuse_access_in *arg)
|
||||
{
|
||||
if (req->f->op.access)
|
||||
req->f->op.access(req, nodeid, arg->mask);
|
||||
else
|
||||
fuse_reply_err(req, ENOSYS);
|
||||
}
|
||||
static void do_readlink(fuse_req_t req, fuse_ino_t nodeid)
|
||||
{
|
||||
if (req->f->op.readlink)
|
||||
@ -927,6 +936,10 @@ void fuse_ll_process_cmd(struct fuse_ll *f, struct fuse_cmd *cmd)
|
||||
case FUSE_SETLKW:
|
||||
do_setlk(req, in->nodeid, 1, (struct fuse_lk_in_out *) inarg);
|
||||
break;
|
||||
|
||||
case FUSE_ACCESS:
|
||||
do_access(req, in->nodeid, (struct fuse_access_in *) inarg);
|
||||
break;
|
||||
|
||||
default:
|
||||
fuse_reply_err(req, ENOSYS);
|
||||
|
Loading…
Reference in New Issue
Block a user