mirror of
https://git.code.sf.net/p/ntfs-3g/ntfs-3g.git
synced 2024-11-23 10:04:00 +08:00
Upgraded fuse-lite to support ioctls
This is backporting code from the full FUSE library in order to support ioctls. The fuse protocol level negociated is now 7.18 instead of 7.8. A fallback protocol to 7.8 is provided for compatibility with older kernels. 32-bit ioctls are not supported by a 64-bit library
This commit is contained in:
parent
9325fa3ca6
commit
ae9aeebbbf
@ -420,8 +420,26 @@ struct fuse_operations {
|
||||
* Introduced in version 2.6
|
||||
*/
|
||||
int (*bmap) (const char *, size_t blocksize, uint64_t *idx);
|
||||
unsigned int flag_nullpath_ok : 1;
|
||||
|
||||
/**
|
||||
* Ioctl
|
||||
*
|
||||
* flags will have FUSE_IOCTL_COMPAT set for 32bit ioctls in
|
||||
* 64bit environment. The size and direction of data is
|
||||
* determined by _IOC_*() decoding of cmd. For _IOC_NONE,
|
||||
* data will be NULL, for _IOC_WRITE data is out area, for
|
||||
* _IOC_READ in area and if both are set in/out area. In all
|
||||
* non-NULL cases, the area is of _IOC_SIZE(cmd) bytes.
|
||||
*
|
||||
* Introduced in version 2.8
|
||||
*/
|
||||
int (*ioctl) (const char *, int cmd, void *arg,
|
||||
struct fuse_file_info *, unsigned int flags, void *data);
|
||||
|
||||
/*
|
||||
* The flags below have been discarded, they should not be used
|
||||
*/
|
||||
unsigned int flag_nullpath_ok : 1;
|
||||
/**
|
||||
* Reserved flags, don't set
|
||||
*/
|
||||
@ -450,10 +468,8 @@ struct fuse_context {
|
||||
/** Private filesystem data */
|
||||
void *private_data;
|
||||
|
||||
#ifdef POSIXACLS
|
||||
/** Umask of the calling process (introduced in version 2.8) */
|
||||
mode_t umask;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* ----------------------------------------------------------- *
|
||||
@ -601,6 +617,8 @@ int fuse_fs_removexattr(struct fuse_fs *fs, const char *path,
|
||||
const char *name);
|
||||
int fuse_fs_bmap(struct fuse_fs *fs, const char *path, size_t blocksize,
|
||||
uint64_t *idx);
|
||||
int fuse_fs_ioctl(struct fuse_fs *fs, const char *path, int cmd, void *arg,
|
||||
struct fuse_file_info *fi, unsigned int flags, void *data);
|
||||
void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn);
|
||||
void fuse_fs_destroy(struct fuse_fs *fs);
|
||||
|
||||
|
@ -49,6 +49,22 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#define FUSE_CAP_BIG_WRITES (1 << 5)
|
||||
#define FUSE_CAP_IOCTL_DIR (1 << 11)
|
||||
|
||||
/**
|
||||
* Ioctl flags
|
||||
*
|
||||
* FUSE_IOCTL_COMPAT: 32bit compat ioctl on 64bit machine
|
||||
* FUSE_IOCTL_UNRESTRICTED: not restricted to well-formed ioctls, retry allowed
|
||||
* FUSE_IOCTL_RETRY: retry with new iovecs
|
||||
* FUSE_IOCTL_DIR: is a directory
|
||||
*/
|
||||
#define FUSE_IOCTL_COMPAT (1 << 0)
|
||||
#define FUSE_IOCTL_UNRESTRICTED (1 << 1)
|
||||
#define FUSE_IOCTL_RETRY (1 << 2)
|
||||
#define FUSE_IOCTL_DIR (1 << 4)
|
||||
|
||||
#define FUSE_IOCTL_MAX_IOV 256
|
||||
|
||||
/**
|
||||
* Information about open files
|
||||
|
@ -48,13 +48,19 @@
|
||||
/** Version number of this interface */
|
||||
#define FUSE_KERNEL_VERSION 7
|
||||
|
||||
/** Minor version number of this interface */
|
||||
#ifdef POSIXACLS
|
||||
#define FUSE_KERNEL_MINOR_VERSION 12
|
||||
/** Minor version number of this interface
|
||||
* We introduce ourself as 7.18 (Posix ACLS : 7.12, IOCTL_DIR : 7.18)
|
||||
* and we expect features features defined for 7.18, but not implemented
|
||||
* here to not be triggered by ntfs-3g.
|
||||
*/
|
||||
#define FUSE_KERNEL_MINOR_VERSION 18
|
||||
|
||||
/*
|
||||
* For binary compatibility with old kernels we accept falling back to 7.8
|
||||
*/
|
||||
|
||||
#define FUSE_KERNEL_MAJOR_FALLBACK 7
|
||||
#define FUSE_KERNEL_MINOR_FALLBACK 8
|
||||
#else
|
||||
#define FUSE_KERNEL_MINOR_VERSION 8
|
||||
#endif
|
||||
|
||||
/** The node ID of the root inode */
|
||||
#define FUSE_ROOT_ID 1
|
||||
@ -83,9 +89,7 @@ struct fuse_attr {
|
||||
__u32 uid;
|
||||
__u32 gid;
|
||||
__u32 rdev;
|
||||
#ifdef POSIXACLS
|
||||
__u64 filling; /* JPA needed for minor >= 12, but meaning unknown */
|
||||
#endif
|
||||
};
|
||||
|
||||
struct fuse_kstatfs {
|
||||
@ -132,11 +136,13 @@ struct fuse_file_lock {
|
||||
* INIT request/reply flags
|
||||
* FUSE_BIG_WRITES: allow big writes to be issued to the file system
|
||||
* FUSE_DONT_MASK: don't apply umask to file mode on create operations
|
||||
* FUSE_HAS_IOCTL_DIR: kernel supports ioctl on directories
|
||||
*/
|
||||
#define FUSE_ASYNC_READ (1 << 0)
|
||||
#define FUSE_POSIX_LOCKS (1 << 1)
|
||||
#define FUSE_BIG_WRITES (1 << 5)
|
||||
#define FUSE_DONT_MASK (1 << 6)
|
||||
#define FUSE_HAS_IOCTL_DIR (1 << 11)
|
||||
|
||||
/**
|
||||
* Release flags
|
||||
@ -180,6 +186,7 @@ enum fuse_opcode {
|
||||
FUSE_INTERRUPT = 36,
|
||||
FUSE_BMAP = 37,
|
||||
FUSE_DESTROY = 38,
|
||||
FUSE_IOCTL = 39,
|
||||
};
|
||||
|
||||
/* The read buffer is required to be at least 8k, but may be much larger */
|
||||
@ -215,10 +222,8 @@ struct fuse_attr_out {
|
||||
struct fuse_mknod_in {
|
||||
__u32 mode;
|
||||
__u32 rdev;
|
||||
#ifdef POSIXACLS
|
||||
__u32 umask;
|
||||
__u32 padding;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct fuse_mkdir_in {
|
||||
@ -255,20 +260,14 @@ struct fuse_setattr_in {
|
||||
|
||||
struct fuse_open_in {
|
||||
__u32 flags;
|
||||
#ifdef POSIXACLS
|
||||
__u32 unused;
|
||||
#else
|
||||
__u32 mode;
|
||||
#endif
|
||||
__u32 mode; /* unused for protocol < 7.12 */
|
||||
};
|
||||
|
||||
struct fuse_create_in {
|
||||
__u32 flags;
|
||||
__u32 mode;
|
||||
#ifdef POSIXACLS
|
||||
__u32 umask;
|
||||
__u32 padding;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct fuse_open_out {
|
||||
@ -305,11 +304,9 @@ struct fuse_write_in {
|
||||
__u64 offset;
|
||||
__u32 size;
|
||||
__u32 write_flags;
|
||||
#ifdef POSIXACLS
|
||||
__u64 lock_owner; /* JPA */
|
||||
__u32 flags; /* JPA */
|
||||
__u32 padding; /* JPA */
|
||||
#endif
|
||||
};
|
||||
|
||||
struct fuse_write_out {
|
||||
@ -389,6 +386,27 @@ struct fuse_bmap_out {
|
||||
__u64 block;
|
||||
};
|
||||
|
||||
struct fuse_ioctl_in {
|
||||
__u64 fh;
|
||||
__u32 flags;
|
||||
__u32 cmd;
|
||||
__u64 arg;
|
||||
__u32 in_size;
|
||||
__u32 out_size;
|
||||
};
|
||||
|
||||
struct fuse_ioctl_iovec {
|
||||
__u64 base;
|
||||
__u64 len;
|
||||
};
|
||||
|
||||
struct fuse_ioctl_out {
|
||||
__s32 result;
|
||||
__u32 flags;
|
||||
__u32 in_iovs;
|
||||
__u32 out_iovs;
|
||||
};
|
||||
|
||||
struct fuse_in_header {
|
||||
__u32 len;
|
||||
__u32 opcode;
|
||||
|
@ -101,10 +101,8 @@ struct fuse_ctx {
|
||||
/** Thread ID of the calling process */
|
||||
pid_t pid;
|
||||
|
||||
#ifdef POSIXACLS
|
||||
/** Umask of the calling process (introduced in version 2.8) */
|
||||
mode_t umask;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* 'to_set' flags in setattr */
|
||||
@ -805,6 +803,37 @@ struct fuse_lowlevel_ops {
|
||||
*/
|
||||
void (*bmap) (fuse_req_t req, fuse_ino_t ino, size_t blocksize,
|
||||
uint64_t idx);
|
||||
/**
|
||||
* Ioctl
|
||||
*
|
||||
* Note: For unrestricted ioctls (not allowed for FUSE
|
||||
* servers), data in and out areas can be discovered by giving
|
||||
* iovs and setting FUSE_IOCTL_RETRY in @flags. For
|
||||
* restricted ioctls, kernel prepares in/out data area
|
||||
* according to the information encoded in cmd.
|
||||
*
|
||||
* Introduced in version 2.8
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_ioctl_retry
|
||||
* fuse_reply_ioctl
|
||||
* fuse_reply_ioctl_iov
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param ino the inode number
|
||||
* @param cmd ioctl command
|
||||
* @param arg ioctl argument
|
||||
* @param fi file information
|
||||
* @param flags for FUSE_IOCTL_* flags
|
||||
* @param in_buf data fetched from the caller
|
||||
* @param in_bufsz number of fetched bytes
|
||||
* @param out_bufsz maximum size of output data
|
||||
*/
|
||||
void (*ioctl) (fuse_req_t req, fuse_ino_t ino, int cmd, void *arg,
|
||||
struct fuse_file_info *fi, unsigned flags,
|
||||
const void *in_buf, size_t in_bufsz, size_t out_bufsz);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1022,6 +1051,20 @@ size_t fuse_add_direntry(fuse_req_t req, char *buf, size_t bufsize,
|
||||
const char *name, const struct stat *stbuf,
|
||||
off_t off);
|
||||
|
||||
/**
|
||||
* Reply to finish ioctl
|
||||
*
|
||||
* Possible requests:
|
||||
* ioctl
|
||||
*
|
||||
* @param req request handle
|
||||
* @param result result to be passed to the caller
|
||||
* @param buf buffer containing output data
|
||||
* @param size length of output data
|
||||
*/
|
||||
int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size);
|
||||
|
||||
|
||||
/* ----------------------------------------------------------- *
|
||||
* Utility functions *
|
||||
* ----------------------------------------------------------- */
|
||||
|
@ -1040,6 +1040,21 @@ int fuse_fs_removexattr(struct fuse_fs *fs, const char *path, const char *name)
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int fuse_fs_ioctl(struct fuse_fs *fs, const char *path, int cmd, void *arg,
|
||||
struct fuse_file_info *fi, unsigned int flags, void *data)
|
||||
{
|
||||
fuse_get_context()->private_data = fs->user_data;
|
||||
if (fs->op.ioctl) {
|
||||
/*
|
||||
if (fs->debug)
|
||||
fprintf(stderr, "ioctl[%llu] 0x%x flags: 0x%x\n",
|
||||
(unsigned long long) fi->fh, cmd, flags);
|
||||
*/
|
||||
return fs->op.ioctl(path, cmd, arg, fi, flags, data);
|
||||
} else
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static int is_open(struct fuse *f, fuse_ino_t dir, const char *name)
|
||||
{
|
||||
struct node *node;
|
||||
@ -2716,6 +2731,60 @@ static void fuse_lib_bmap(fuse_req_t req, fuse_ino_t ino, size_t blocksize,
|
||||
reply_err(req, err);
|
||||
}
|
||||
|
||||
static void fuse_lib_ioctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg,
|
||||
struct fuse_file_info *llfi, unsigned int flags,
|
||||
const void *in_buf, size_t in_bufsz,
|
||||
size_t out_bufsz)
|
||||
{
|
||||
struct fuse *f = req_fuse_prepare(req);
|
||||
struct fuse_intr_data d;
|
||||
struct fuse_file_info fi;
|
||||
char *path, *out_buf = NULL;
|
||||
int err;
|
||||
|
||||
err = -EPERM;
|
||||
if (flags & FUSE_IOCTL_UNRESTRICTED)
|
||||
goto err;
|
||||
|
||||
if (flags & FUSE_IOCTL_DIR)
|
||||
get_dirhandle(llfi, &fi);
|
||||
else
|
||||
fi = *llfi;
|
||||
|
||||
if (out_bufsz) {
|
||||
err = -ENOMEM;
|
||||
out_buf = malloc(out_bufsz);
|
||||
if (!out_buf)
|
||||
goto err;
|
||||
}
|
||||
|
||||
assert(!in_bufsz || !out_bufsz || in_bufsz == out_bufsz);
|
||||
if (out_buf)
|
||||
memcpy(out_buf, in_buf, in_bufsz);
|
||||
|
||||
path = get_path(f, ino); /* Should be get_path_nullok() */
|
||||
if (!path) {
|
||||
err = ENOENT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
fuse_prepare_interrupt(f, req, &d);
|
||||
|
||||
/* Note : const qualifier dropped */
|
||||
err = fuse_fs_ioctl(f->fs, path, cmd, arg, &fi, flags,
|
||||
out_buf ? (void*)out_buf : (void*)(uintptr_t)in_buf);
|
||||
|
||||
fuse_finish_interrupt(f, req, &d);
|
||||
free(path);
|
||||
|
||||
fuse_reply_ioctl(req, err, out_buf, out_bufsz);
|
||||
goto out;
|
||||
err:
|
||||
reply_err(req, err);
|
||||
out:
|
||||
free(out_buf);
|
||||
}
|
||||
|
||||
static struct fuse_lowlevel_ops fuse_path_ops = {
|
||||
.init = fuse_lib_init,
|
||||
.destroy = fuse_lib_destroy,
|
||||
@ -2751,6 +2820,7 @@ static struct fuse_lowlevel_ops fuse_path_ops = {
|
||||
.getlk = fuse_lib_getlk,
|
||||
.setlk = fuse_lib_setlk,
|
||||
.bmap = fuse_lib_bmap,
|
||||
.ioctl = fuse_lib_ioctl,
|
||||
};
|
||||
|
||||
struct fuse_session *fuse_get_session(struct fuse *f)
|
||||
|
@ -333,12 +333,8 @@ int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e)
|
||||
|
||||
memset(&arg, 0, sizeof(arg));
|
||||
fill_entry(&arg, e);
|
||||
#ifdef POSIXACLS
|
||||
return send_reply_ok(req, &arg, (req->f->conn.proto_minor >= 12
|
||||
? sizeof(arg) : FUSE_COMPAT_ENTRY_OUT_SIZE));
|
||||
#else
|
||||
return send_reply_ok(req, &arg, sizeof(arg));
|
||||
#endif
|
||||
}
|
||||
|
||||
int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e,
|
||||
@ -351,7 +347,6 @@ int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e,
|
||||
|
||||
memset(&arg, 0, sizeof(arg));
|
||||
fill_entry(&arg.e, e);
|
||||
#ifdef POSIXACLS
|
||||
if (req->f->conn.proto_minor < 12) {
|
||||
fill_open((struct fuse_open_out*)
|
||||
((char*)&arg + FUSE_COMPAT_ENTRY_OUT_SIZE), f);
|
||||
@ -361,10 +356,6 @@ int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e,
|
||||
fill_open(&arg.o, f);
|
||||
return send_reply_ok(req, &arg, sizeof(arg));
|
||||
}
|
||||
#else
|
||||
fill_open(&arg.o, f);
|
||||
return send_reply_ok(req, &arg, sizeof(arg));
|
||||
#endif
|
||||
}
|
||||
|
||||
int fuse_reply_attr(fuse_req_t req, const struct stat *attr,
|
||||
@ -377,12 +368,8 @@ int fuse_reply_attr(fuse_req_t req, const struct stat *attr,
|
||||
arg.attr_valid_nsec = calc_timeout_nsec(attr_timeout);
|
||||
convert_stat(attr, &arg.attr);
|
||||
|
||||
#ifdef POSIXACLS
|
||||
return send_reply_ok(req, &arg, (req->f->conn.proto_minor >= 12
|
||||
? sizeof(arg) : FUSE_COMPAT_FUSE_ATTR_OUT_SIZE));
|
||||
#else
|
||||
return send_reply_ok(req, &arg, sizeof(arg));
|
||||
#endif
|
||||
}
|
||||
|
||||
int fuse_reply_readlink(fuse_req_t req, const char *linkname)
|
||||
@ -462,6 +449,28 @@ int fuse_reply_bmap(fuse_req_t req, uint64_t idx)
|
||||
return send_reply_ok(req, &arg, sizeof(arg));
|
||||
}
|
||||
|
||||
int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size)
|
||||
{
|
||||
struct fuse_ioctl_out arg;
|
||||
struct iovec iov[3];
|
||||
size_t count = 1;
|
||||
|
||||
memset(&arg, 0, sizeof(arg));
|
||||
arg.result = result;
|
||||
iov[count].iov_base = &arg;
|
||||
iov[count].iov_len = sizeof(arg);
|
||||
count++;
|
||||
|
||||
if (size) {
|
||||
/* Note : const qualifier dropped */
|
||||
iov[count].iov_base = (char *)(uintptr_t) buf;
|
||||
iov[count].iov_len = size;
|
||||
count++;
|
||||
}
|
||||
|
||||
return send_reply_iov(req, 0, iov, count);
|
||||
}
|
||||
|
||||
static void do_lookup(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
|
||||
{
|
||||
const char *name = (const char *) inarg;
|
||||
@ -538,11 +547,9 @@ static void do_mknod(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
|
||||
const struct fuse_mknod_in *arg = (const struct fuse_mknod_in *) inarg;
|
||||
const char *name = PARAM(arg);
|
||||
|
||||
#ifdef POSIXACLS
|
||||
if (req->f->conn.proto_minor >= 12)
|
||||
req->ctx.umask = arg->umask;
|
||||
else
|
||||
#endif
|
||||
name = (const char *) inarg + FUSE_COMPAT_MKNOD_IN_SIZE;
|
||||
|
||||
if (req->f->op.mknod)
|
||||
@ -555,10 +562,8 @@ static void do_mkdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
|
||||
{
|
||||
const struct fuse_mkdir_in *arg = (const struct fuse_mkdir_in *) inarg;
|
||||
|
||||
#ifdef POSIXACLS
|
||||
if (req->f->conn.proto_minor >= 12)
|
||||
req->ctx.umask = arg->umask;
|
||||
#endif
|
||||
|
||||
if (req->f->op.mkdir)
|
||||
req->f->op.mkdir(req, nodeid, PARAM(arg), arg->mode);
|
||||
@ -630,11 +635,9 @@ static void do_create(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
|
||||
memset(&fi, 0, sizeof(fi));
|
||||
fi.flags = arg->flags;
|
||||
|
||||
#ifdef POSIXACLS
|
||||
if (req->f->conn.proto_minor >= 12)
|
||||
req->ctx.umask = arg->umask;
|
||||
else
|
||||
#endif
|
||||
name = (const char *) inarg + sizeof(struct fuse_open_in);
|
||||
|
||||
req->f->op.create(req, nodeid, name, arg->mode, &fi);
|
||||
@ -682,7 +685,6 @@ static void do_write(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
|
||||
fi.writepage = arg->write_flags & 1;
|
||||
|
||||
if (req->f->op.write) {
|
||||
#ifdef POSIXACLS
|
||||
const char *buf;
|
||||
|
||||
if (req->f->conn.proto_minor >= 12)
|
||||
@ -690,9 +692,6 @@ static void do_write(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
|
||||
else
|
||||
buf = ((const char*)arg) + FUSE_COMPAT_WRITE_IN_SIZE;
|
||||
req->f->op.write(req, nodeid, buf, arg->size, arg->offset, &fi);
|
||||
#else
|
||||
req->f->op.write(req, nodeid, PARAM(arg), arg->size, arg->offset, &fi);
|
||||
#endif
|
||||
} else
|
||||
fuse_reply_err(req, ENOSYS);
|
||||
}
|
||||
@ -1011,6 +1010,39 @@ static void do_bmap(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
|
||||
fuse_reply_err(req, ENOSYS);
|
||||
}
|
||||
|
||||
static void do_ioctl(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
|
||||
{
|
||||
const struct fuse_ioctl_in *arg = (const struct fuse_ioctl_in *) inarg;
|
||||
unsigned int flags = arg->flags;
|
||||
const void *in_buf = arg->in_size ? PARAM(arg) : NULL;
|
||||
struct fuse_file_info fi;
|
||||
|
||||
if (flags & FUSE_IOCTL_DIR &&
|
||||
!(req->f->conn.want & FUSE_CAP_IOCTL_DIR)) {
|
||||
fuse_reply_err(req, ENOTTY);
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&fi, 0, sizeof(fi));
|
||||
fi.fh = arg->fh;
|
||||
|
||||
/* TODO JPA (need req->ioctl_64bit in obscure fuse_req_t)
|
||||
// probably a 64 bit ioctl on a 32-bit cpu
|
||||
// this is to forward a request from the kernel
|
||||
if (sizeof(void *) == 4 && req->f->conn.proto_minor >= 16 &&
|
||||
!(flags & FUSE_IOCTL_32BIT)) {
|
||||
req->ioctl_64bit = 1;
|
||||
}
|
||||
*/
|
||||
|
||||
if (req->f->op.ioctl)
|
||||
req->f->op.ioctl(req, nodeid, arg->cmd,
|
||||
(void *)(uintptr_t)arg->arg, &fi, flags,
|
||||
in_buf, arg->in_size, arg->out_size);
|
||||
else
|
||||
fuse_reply_err(req, ENOSYS);
|
||||
}
|
||||
|
||||
static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
|
||||
{
|
||||
const struct fuse_init_in *arg = (const struct fuse_init_in *) inarg;
|
||||
@ -1047,6 +1079,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
|
||||
#endif
|
||||
if (arg->flags & FUSE_BIG_WRITES)
|
||||
f->conn.capable |= FUSE_CAP_BIG_WRITES;
|
||||
if (arg->flags & FUSE_HAS_IOCTL_DIR)
|
||||
f->conn.capable |= FUSE_CAP_IOCTL_DIR;
|
||||
} else {
|
||||
f->conn.async_read = 0;
|
||||
f->conn.max_readahead = 0;
|
||||
@ -1069,28 +1103,28 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
|
||||
memset(&outarg, 0, sizeof(outarg));
|
||||
outarg.major = FUSE_KERNEL_VERSION;
|
||||
/*
|
||||
* if POSIXACLS is not set, protocol 7.8 provides a good
|
||||
* compatibility with older kernel modules.
|
||||
* if POSIXACLS is set, we try to use protocol 7.12 supposed
|
||||
* to have the ability to process the umask conditionnally,
|
||||
* but, when using an older kernel module, we fallback to 7.8
|
||||
* Suggest using protocol 7.18 when available, and fallback
|
||||
* to 7.8 when running on an old kernel.
|
||||
* Protocol 7.12 has the ability to process the umask
|
||||
* conditionnally (as needed if POSIXACLS is set)
|
||||
* Protocol 7.18 has the ability to process the ioctls
|
||||
*/
|
||||
#ifdef POSIXACLS
|
||||
if (arg->major > 7 || (arg->major == 7 && arg->minor >= 12))
|
||||
if (arg->major > 7 || (arg->major == 7 && arg->minor >= 18)) {
|
||||
outarg.minor = FUSE_KERNEL_MINOR_VERSION;
|
||||
else
|
||||
outarg.minor = FUSE_KERNEL_MINOR_FALLBACK;
|
||||
#else
|
||||
outarg.minor = FUSE_KERNEL_MINOR_VERSION;
|
||||
if (f->conn.want & FUSE_CAP_IOCTL_DIR)
|
||||
outarg.flags |= FUSE_HAS_IOCTL_DIR;
|
||||
#ifdef POSIXACLS
|
||||
if (f->conn.want & FUSE_CAP_DONT_MASK)
|
||||
outarg.flags |= FUSE_DONT_MASK;
|
||||
#endif
|
||||
} else {
|
||||
outarg.major = FUSE_KERNEL_MAJOR_FALLBACK;
|
||||
outarg.minor = FUSE_KERNEL_MINOR_FALLBACK;
|
||||
}
|
||||
if (f->conn.async_read)
|
||||
outarg.flags |= FUSE_ASYNC_READ;
|
||||
if (f->op.getlk && f->op.setlk)
|
||||
outarg.flags |= FUSE_POSIX_LOCKS;
|
||||
#ifdef POSIXACLS
|
||||
if (f->conn.want & FUSE_CAP_DONT_MASK)
|
||||
outarg.flags |= FUSE_DONT_MASK;
|
||||
#endif
|
||||
if (f->conn.want & FUSE_CAP_BIG_WRITES)
|
||||
outarg.flags |= FUSE_BIG_WRITES;
|
||||
outarg.max_readahead = f->conn.max_readahead;
|
||||
@ -1191,6 +1225,7 @@ static struct {
|
||||
[FUSE_CREATE] = { do_create, "CREATE" },
|
||||
[FUSE_INTERRUPT] = { do_interrupt, "INTERRUPT" },
|
||||
[FUSE_BMAP] = { do_bmap, "BMAP" },
|
||||
[FUSE_IOCTL] = { do_ioctl, "IOCTL" },
|
||||
[FUSE_DESTROY] = { do_destroy, "DESTROY" },
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user