mirror of
https://github.com/openharmony/third_party_libfuse.git
synced 2026-07-18 10:34:54 -04:00
CUSE patches from Tejun Heo
This commit is contained in:
@@ -1,3 +1,34 @@
|
||||
2009-06-18 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
* CUSE patches from Tejun Heo:
|
||||
|
||||
* Unrestricted ioctl support left some debris. Clean them up:
|
||||
o No reason to pass around pointer to flags. Pass flags directly.
|
||||
o Clean up comment and prototype parameter names.
|
||||
o fuse_lib_ioctl() didn't reply when get_path() failed. Fix it.
|
||||
o Remove unused variables {in|out}_iov from fuse_lib_ioctl().
|
||||
|
||||
* Add fuse_reply_ioctl_iov()
|
||||
|
||||
* Move fuse_session, fuse_req and fuse_ll definitions to fuse_i.h
|
||||
and make send_reply_iov() and fuse_setup_common() global (also in
|
||||
fuse_i.h). These will be used by CUSE support.
|
||||
|
||||
* Restructure fuse_ll_process()
|
||||
|
||||
* Implement libfuse side of CUSE support. CUSE uses subset of FUSE
|
||||
operations as dir operations don't make sense for CUSE where one
|
||||
instance implements single character device.
|
||||
|
||||
CUSE support comes with its own cuse_lowevel_ops and related
|
||||
initialization and helper functions. Except for initialization, it
|
||||
usage is basically identical to FUSE.
|
||||
|
||||
This patch also adds example/cusexmp.c which can create a character
|
||||
device with name and device number specified on command line. The
|
||||
created device itself is pretty boring. It's a bit bucket supporting
|
||||
read, write and access via ioctl.
|
||||
|
||||
2009-06-16 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
* Add missing fuse_reply_bmap to versionscript. Debian
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include -D_FILE_OFFSET_BITS=64 -D_REENTRANT
|
||||
noinst_HEADERS = fioc.h
|
||||
noinst_PROGRAMS = fusexmp fusexmp_fh null hello hello_ll fioc fioclient \
|
||||
fsel fselclient
|
||||
fsel fselclient cusexmp
|
||||
|
||||
LDADD = ../lib/libfuse.la @libfuse_libs@
|
||||
fusexmp_fh_LDADD = ../lib/libfuse.la ../lib/libulockmgr.la @libfuse_libs@
|
||||
|
||||
+17
-2
@@ -12,6 +12,21 @@
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
enum {
|
||||
FIOC_GET_SIZE = _IOR('E', 0, size_t),
|
||||
FIOC_SET_SIZE = _IOW('E', 1, size_t),
|
||||
FIOC_GET_SIZE = _IOR('E', 0, size_t),
|
||||
FIOC_SET_SIZE = _IOW('E', 1, size_t),
|
||||
|
||||
/*
|
||||
* The following two ioctls don't follow usual encoding rules
|
||||
* and transfer variable amount of data.
|
||||
*/
|
||||
FIOC_READ = _IO('E', 2),
|
||||
FIOC_WRITE = _IO('E', 3),
|
||||
};
|
||||
|
||||
struct fioc_rw_arg {
|
||||
off_t offset;
|
||||
void *buf;
|
||||
size_t size;
|
||||
size_t prev_size; /* out param for previous total size */
|
||||
size_t new_size; /* out param for new total size */
|
||||
};
|
||||
|
||||
+79
-23
@@ -20,19 +20,56 @@
|
||||
#include "fioc.h"
|
||||
|
||||
const char *usage =
|
||||
"Usage: fioclient FIOC_FILE [SIZE]\n"
|
||||
"Usage: fioclient FIOC_FILE COMMAND\n"
|
||||
"\n"
|
||||
" get size if SIZE is omitted, set size otherwise\n"
|
||||
"COMMANDS\n"
|
||||
" s [SIZE] : get size if SIZE is omitted, set size otherwise\n"
|
||||
" r SIZE [OFF] : read SIZE bytes @ OFF (dfl 0) and output to stdout\n"
|
||||
" w SIZE [OFF] : write SIZE bytes @ OFF (dfl 0) from stdin\n"
|
||||
"\n";
|
||||
|
||||
static int do_rw(int fd, int is_read, size_t size, off_t offset,
|
||||
size_t *prev_size, size_t *new_size)
|
||||
{
|
||||
struct fioc_rw_arg arg = { .offset = offset };
|
||||
ssize_t ret;
|
||||
|
||||
arg.buf = calloc(1, size);
|
||||
if (!arg.buf) {
|
||||
fprintf(stderr, "failed to allocated %zu bytes\n", size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (is_read) {
|
||||
arg.size = size;
|
||||
ret = ioctl(fd, FIOC_READ, &arg);
|
||||
if (ret >= 0)
|
||||
fwrite(arg.buf, 1, ret, stdout);
|
||||
} else {
|
||||
arg.size = fread(arg.buf, 1, size, stdin);
|
||||
fprintf(stderr, "Writing %zu bytes\n", arg.size);
|
||||
ret = ioctl(fd, FIOC_WRITE, &arg);
|
||||
}
|
||||
|
||||
if (ret >= 0) {
|
||||
*prev_size = arg.prev_size;
|
||||
*new_size = arg.new_size;
|
||||
} else
|
||||
perror("ioctl");
|
||||
|
||||
free(arg.buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
size_t size;
|
||||
int fd;
|
||||
size_t param[2] = { };
|
||||
size_t size, prev_size = 0, new_size = 0;
|
||||
char cmd;
|
||||
int fd, i, rc;
|
||||
|
||||
if (argc < 2) {
|
||||
if (argc < 3)
|
||||
goto usage;
|
||||
}
|
||||
|
||||
fd = open(argv[1], O_RDWR);
|
||||
if (fd < 0) {
|
||||
@@ -40,27 +77,46 @@ int main(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (argc == 2) {
|
||||
if (ioctl(fd, FIOC_GET_SIZE, &size)) {
|
||||
perror("ioctl");
|
||||
return 1;
|
||||
}
|
||||
printf("%zu\n", size);
|
||||
} else {
|
||||
cmd = tolower(argv[2][0]);
|
||||
argc -= 3;
|
||||
argv += 3;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
char *endp;
|
||||
|
||||
size = strtoul(argv[2], &endp, 0);
|
||||
if (endp == argv[2] || *endp != '\0')
|
||||
param[i] = strtoul(argv[i], &endp, 0);
|
||||
if (endp == argv[i] || *endp != '\0')
|
||||
goto usage;
|
||||
|
||||
if (ioctl(fd, FIOC_SET_SIZE, &size)) {
|
||||
perror("ioctl");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
usage:
|
||||
switch (cmd) {
|
||||
case 's':
|
||||
if (!argc) {
|
||||
if (ioctl(fd, FIOC_GET_SIZE, &size)) {
|
||||
perror("ioctl");
|
||||
return 1;
|
||||
}
|
||||
printf("%zu\n", size);
|
||||
} else {
|
||||
size = param[0];
|
||||
if (ioctl(fd, FIOC_SET_SIZE, &size)) {
|
||||
perror("ioctl");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
case 'r':
|
||||
case 'w':
|
||||
rc = do_rw(fd, cmd == 'r', param[0], param[1],
|
||||
&prev_size, &new_size);
|
||||
if (rc < 0)
|
||||
return 1;
|
||||
fprintf(stderr, "transferred %d bytes (%zu -> %zu)\n",
|
||||
rc, prev_size, new_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
usage:
|
||||
fprintf(stderr, usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
+2
-1
@@ -9,7 +9,8 @@ fuseinclude_HEADERS = \
|
||||
fuse_common_compat.h \
|
||||
fuse_lowlevel.h \
|
||||
fuse_lowlevel_compat.h \
|
||||
fuse_opt.h
|
||||
fuse_opt.h \
|
||||
cuse_lowlevel.h
|
||||
|
||||
include_HEADERS = old/fuse.h ulockmgr.h
|
||||
|
||||
|
||||
@@ -149,6 +149,13 @@ struct fuse_file_lock {
|
||||
#define FUSE_EXPORT_SUPPORT (1 << 4)
|
||||
#define FUSE_BIG_WRITES (1 << 5)
|
||||
|
||||
/**
|
||||
* CUSE INIT request/reply flags
|
||||
*
|
||||
* CUSE_UNRESTRICTED_IOCTL: use unrestricted ioctl
|
||||
*/
|
||||
#define CUSE_UNRESTRICTED_IOCTL (1 << 0)
|
||||
|
||||
/**
|
||||
* Release flags
|
||||
*/
|
||||
@@ -239,6 +246,9 @@ enum fuse_opcode {
|
||||
FUSE_DESTROY = 38,
|
||||
FUSE_IOCTL = 39,
|
||||
FUSE_POLL = 40,
|
||||
|
||||
/* CUSE specific operations */
|
||||
CUSE_INIT = 4096,
|
||||
};
|
||||
|
||||
enum fuse_notify_code {
|
||||
@@ -430,6 +440,27 @@ struct fuse_init_out {
|
||||
__u32 max_write;
|
||||
};
|
||||
|
||||
#define CUSE_INIT_INFO_MAX 4096
|
||||
|
||||
struct cuse_init_in {
|
||||
__u32 major;
|
||||
__u32 minor;
|
||||
__u32 unused;
|
||||
__u32 flags;
|
||||
};
|
||||
|
||||
struct cuse_init_out {
|
||||
__u32 major;
|
||||
__u32 minor;
|
||||
__u32 unused;
|
||||
__u32 flags;
|
||||
__u32 max_read;
|
||||
__u32 max_write;
|
||||
__u32 dev_major; /* chardev major */
|
||||
__u32 dev_minor; /* chardev minor */
|
||||
__u32 spare[10];
|
||||
};
|
||||
|
||||
struct fuse_interrupt_in {
|
||||
__u64 unique;
|
||||
};
|
||||
|
||||
+21
-6
@@ -815,7 +815,7 @@ struct fuse_lowlevel_ops {
|
||||
*
|
||||
* 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 *flagsp. For
|
||||
* iovs and setting FUSE_IOCTL_RETRY in @flags. For
|
||||
* restricted ioctls, kernel prepares in/out data area
|
||||
* according to the information encoded in cmd.
|
||||
*
|
||||
@@ -824,6 +824,7 @@ struct fuse_lowlevel_ops {
|
||||
* Valid replies:
|
||||
* fuse_reply_ioctl_retry
|
||||
* fuse_reply_ioctl
|
||||
* fuse_reply_ioctl_iov
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
@@ -831,14 +832,14 @@ struct fuse_lowlevel_ops {
|
||||
* @param cmd ioctl command
|
||||
* @param arg ioctl argument
|
||||
* @param fi file information
|
||||
* @param flagsp io/out parameter for FUSE_IOCTL_* flags
|
||||
* @param flags for FUSE_IOCTL_* flags
|
||||
* @param in_buf data fetched from the caller
|
||||
* @param in_size number of fetched bytes
|
||||
* @param out_size maximum size of output data
|
||||
* @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 *flagsp,
|
||||
const void *in_buf, size_t in_bufsz, size_t out_bufszp);
|
||||
struct fuse_file_info *fi, unsigned flags,
|
||||
const void *in_buf, size_t in_bufsz, size_t out_bufsz);
|
||||
|
||||
/**
|
||||
* Poll for IO readiness
|
||||
@@ -1115,6 +1116,20 @@ int fuse_reply_ioctl_retry(fuse_req_t req,
|
||||
*/
|
||||
int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size);
|
||||
|
||||
/**
|
||||
* Reply to finish ioctl with iov buffer
|
||||
*
|
||||
* Possible requests:
|
||||
* ioctl
|
||||
*
|
||||
* @param req request handle
|
||||
* @param result result to be passed to the caller
|
||||
* @param iov the vector containing the data
|
||||
* @param count the size of vector
|
||||
*/
|
||||
int fuse_reply_ioctl_iov(fuse_req_t req, int result, const struct iovec *iov,
|
||||
int count);
|
||||
|
||||
/**
|
||||
* Reply with poll result event mask
|
||||
*
|
||||
|
||||
@@ -29,6 +29,7 @@ libfuse_la_SOURCES = \
|
||||
fuse_opt.c \
|
||||
fuse_session.c \
|
||||
fuse_signals.c \
|
||||
cuse_lowlevel.c \
|
||||
helper.c \
|
||||
modules/subdir.c \
|
||||
$(iconv_source) \
|
||||
|
||||
+11
-17
@@ -3211,25 +3211,24 @@ static void fuse_lib_bmap(fuse_req_t req, fuse_ino_t ino, size_t blocksize,
|
||||
}
|
||||
|
||||
static void fuse_lib_ioctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg,
|
||||
struct fuse_file_info *fi, unsigned int *flagsp,
|
||||
struct fuse_file_info *fi, 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;
|
||||
char *path, *out_buf = NULL;
|
||||
struct iovec *in_iov = NULL, *out_iov = NULL;
|
||||
int err;
|
||||
|
||||
if (*flagsp & FUSE_IOCTL_UNRESTRICTED) {
|
||||
reply_err(req, -EPERM);
|
||||
return;
|
||||
}
|
||||
err = -EPERM;
|
||||
if (flags & FUSE_IOCTL_UNRESTRICTED)
|
||||
goto err;
|
||||
|
||||
if (out_bufsz) {
|
||||
err = -ENOMEM;
|
||||
out_buf = malloc(out_bufsz);
|
||||
if (!out_buf)
|
||||
goto enomem;
|
||||
goto err;
|
||||
}
|
||||
|
||||
assert(!in_bufsz || !out_bufsz || in_bufsz == out_bufsz);
|
||||
@@ -3238,27 +3237,22 @@ static void fuse_lib_ioctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg,
|
||||
|
||||
err = get_path(f, ino, &path);
|
||||
if (err)
|
||||
goto out;
|
||||
goto err;
|
||||
|
||||
fuse_prepare_interrupt(f, req, &d);
|
||||
|
||||
err = fuse_fs_ioctl(f->fs, path, cmd, arg, fi, *flagsp,
|
||||
err = fuse_fs_ioctl(f->fs, path, cmd, arg, fi, flags,
|
||||
out_buf ?: (void *)in_buf);
|
||||
|
||||
fuse_finish_interrupt(f, req, &d);
|
||||
free_path(f, ino, path);
|
||||
|
||||
fuse_reply_ioctl(req, err, out_buf, out_bufsz);
|
||||
|
||||
goto out;
|
||||
err:
|
||||
reply_err(req, err);
|
||||
out:
|
||||
free(out_buf);
|
||||
free(in_iov);
|
||||
free(out_iov);
|
||||
return;
|
||||
|
||||
enomem:
|
||||
reply_err(req, -ENOMEM);
|
||||
goto out;
|
||||
}
|
||||
|
||||
static void fuse_lib_poll(fuse_req_t req, fuse_ino_t ino,
|
||||
|
||||
+66
-3
@@ -7,11 +7,58 @@
|
||||
*/
|
||||
|
||||
#include "fuse.h"
|
||||
#include "fuse_lowlevel.h"
|
||||
|
||||
struct fuse_session;
|
||||
struct fuse_chan;
|
||||
struct fuse_lowlevel_ops;
|
||||
struct fuse_req;
|
||||
struct fuse_ll;
|
||||
|
||||
struct fuse_session {
|
||||
struct fuse_session_ops op;
|
||||
|
||||
void *data;
|
||||
|
||||
volatile int exited;
|
||||
|
||||
struct fuse_chan *ch;
|
||||
};
|
||||
|
||||
struct fuse_req {
|
||||
struct fuse_ll *f;
|
||||
uint64_t unique;
|
||||
int ctr;
|
||||
pthread_mutex_t lock;
|
||||
struct fuse_ctx ctx;
|
||||
struct fuse_chan *ch;
|
||||
int interrupted;
|
||||
union {
|
||||
struct {
|
||||
uint64_t unique;
|
||||
} i;
|
||||
struct {
|
||||
fuse_interrupt_func_t func;
|
||||
void *data;
|
||||
} ni;
|
||||
} u;
|
||||
struct fuse_req *next;
|
||||
struct fuse_req *prev;
|
||||
};
|
||||
|
||||
struct fuse_ll {
|
||||
int debug;
|
||||
int allow_root;
|
||||
int atomic_o_trunc;
|
||||
int big_writes;
|
||||
struct fuse_lowlevel_ops op;
|
||||
int got_init;
|
||||
struct cuse_data *cuse_data;
|
||||
void *userdata;
|
||||
uid_t owner;
|
||||
struct fuse_conn_info conn;
|
||||
struct fuse_req list;
|
||||
struct fuse_req interrupts;
|
||||
pthread_mutex_t lock;
|
||||
int got_destroy;
|
||||
};
|
||||
|
||||
struct fuse_cmd {
|
||||
char *buf;
|
||||
@@ -34,3 +81,19 @@ struct fuse_session *fuse_lowlevel_new_common(struct fuse_args *args,
|
||||
void fuse_kern_unmount_compat22(const char *mountpoint);
|
||||
void fuse_kern_unmount(const char *mountpoint, int fd);
|
||||
int fuse_kern_mount(const char *mountpoint, struct fuse_args *args);
|
||||
|
||||
int send_reply_iov(fuse_req_t req, int error, struct iovec *iov, int count);
|
||||
int send_reply_iov_nofree(fuse_req_t req, int error, struct iovec *iov, int count);
|
||||
void free_req(fuse_req_t req);
|
||||
|
||||
|
||||
struct fuse *fuse_setup_common(int argc, char *argv[],
|
||||
const struct fuse_operations *op,
|
||||
size_t op_size,
|
||||
char **mountpoint,
|
||||
int *multithreaded,
|
||||
int *fd,
|
||||
void *user_data,
|
||||
int compat);
|
||||
|
||||
void do_cuse_init(fuse_req_t req, fuse_ino_t nodeide, const void *inarg);
|
||||
|
||||
+71
-65
@@ -6,10 +6,9 @@
|
||||
See the file COPYING.LIB
|
||||
*/
|
||||
|
||||
#include "fuse_lowlevel.h"
|
||||
#include "fuse_i.h"
|
||||
#include "fuse_kernel.h"
|
||||
#include "fuse_opt.h"
|
||||
#include "fuse_i.h"
|
||||
#include "fuse_misc.h"
|
||||
#include "fuse_common_compat.h"
|
||||
#include "fuse_lowlevel_compat.h"
|
||||
@@ -25,45 +24,6 @@
|
||||
#define PARAM(inarg) (((char *)(inarg)) + sizeof(*(inarg)))
|
||||
#define OFFSET_MAX 0x7fffffffffffffffLL
|
||||
|
||||
struct fuse_ll;
|
||||
|
||||
struct fuse_req {
|
||||
struct fuse_ll *f;
|
||||
uint64_t unique;
|
||||
int ctr;
|
||||
pthread_mutex_t lock;
|
||||
struct fuse_ctx ctx;
|
||||
struct fuse_chan *ch;
|
||||
int interrupted;
|
||||
union {
|
||||
struct {
|
||||
uint64_t unique;
|
||||
} i;
|
||||
struct {
|
||||
fuse_interrupt_func_t func;
|
||||
void *data;
|
||||
} ni;
|
||||
} u;
|
||||
struct fuse_req *next;
|
||||
struct fuse_req *prev;
|
||||
};
|
||||
|
||||
struct fuse_ll {
|
||||
int debug;
|
||||
int allow_root;
|
||||
int atomic_o_trunc;
|
||||
int big_writes;
|
||||
struct fuse_lowlevel_ops op;
|
||||
int got_init;
|
||||
void *userdata;
|
||||
uid_t owner;
|
||||
struct fuse_conn_info conn;
|
||||
struct fuse_req list;
|
||||
struct fuse_req interrupts;
|
||||
pthread_mutex_t lock;
|
||||
int got_destroy;
|
||||
};
|
||||
|
||||
struct fuse_pollhandle {
|
||||
uint64_t kh;
|
||||
struct fuse_chan *ch;
|
||||
@@ -140,7 +100,7 @@ static void destroy_req(fuse_req_t req)
|
||||
free(req);
|
||||
}
|
||||
|
||||
static void free_req(fuse_req_t req)
|
||||
void free_req(fuse_req_t req)
|
||||
{
|
||||
int ctr;
|
||||
struct fuse_ll *f = req->f;
|
||||
@@ -155,11 +115,10 @@ static void free_req(fuse_req_t req)
|
||||
destroy_req(req);
|
||||
}
|
||||
|
||||
static int send_reply_iov(fuse_req_t req, int error, struct iovec *iov,
|
||||
int send_reply_iov_nofree(fuse_req_t req, int error, struct iovec *iov,
|
||||
int count)
|
||||
{
|
||||
struct fuse_out_header out;
|
||||
int res;
|
||||
|
||||
if (error <= -1000 || error > 0) {
|
||||
fprintf(stderr, "fuse: bad error value: %i\n", error);
|
||||
@@ -184,9 +143,16 @@ static int send_reply_iov(fuse_req_t req, int error, struct iovec *iov,
|
||||
(unsigned long long) out.unique, out.len);
|
||||
}
|
||||
}
|
||||
res = fuse_chan_send(req->ch, iov, count);
|
||||
free_req(req);
|
||||
|
||||
return fuse_chan_send(req->ch, iov, count);
|
||||
}
|
||||
|
||||
int send_reply_iov(fuse_req_t req, int error, struct iovec *iov, int count)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = send_reply_iov_nofree(req, error, iov, count);
|
||||
free_req(req);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -509,6 +475,30 @@ int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size)
|
||||
return send_reply_iov(req, 0, iov, count);
|
||||
}
|
||||
|
||||
int fuse_reply_ioctl_iov(fuse_req_t req, int result, const struct iovec *iov,
|
||||
int count)
|
||||
{
|
||||
struct iovec *padded_iov;
|
||||
struct fuse_ioctl_out arg;
|
||||
int res;
|
||||
|
||||
padded_iov = malloc((count + 2) * sizeof(struct iovec));
|
||||
if (padded_iov == NULL)
|
||||
return fuse_reply_err(req, -ENOMEM);
|
||||
|
||||
memset(&arg, 0, sizeof(arg));
|
||||
arg.result = result;
|
||||
padded_iov[1].iov_base = &arg;
|
||||
padded_iov[1].iov_len = sizeof(arg);
|
||||
|
||||
memcpy(&padded_iov[2], iov, count * sizeof(struct iovec));
|
||||
|
||||
res = send_reply_iov(req, 0, padded_iov, count + 2);
|
||||
free(padded_iov);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int fuse_reply_poll(fuse_req_t req, unsigned revents)
|
||||
{
|
||||
struct fuse_poll_out arg;
|
||||
@@ -1095,7 +1085,7 @@ static void do_ioctl(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
|
||||
|
||||
if (req->f->op.ioctl)
|
||||
req->f->op.ioctl(req, nodeid, arg->cmd,
|
||||
(void *)(uintptr_t)arg->arg, &fi, &flags,
|
||||
(void *)(uintptr_t)arg->arg, &fi, flags,
|
||||
in_buf, arg->in_size, arg->out_size);
|
||||
else
|
||||
fuse_reply_err(req, ENOSYS);
|
||||
@@ -1356,6 +1346,7 @@ static struct {
|
||||
[FUSE_IOCTL] = { do_ioctl, "IOCTL" },
|
||||
[FUSE_POLL] = { do_poll, "POLL" },
|
||||
[FUSE_DESTROY] = { do_destroy, "DESTROY" },
|
||||
[CUSE_INIT] = { do_cuse_init, "CUSE_INIT" },
|
||||
};
|
||||
|
||||
#define FUSE_MAXOP (sizeof(fuse_ll_ops) / sizeof(fuse_ll_ops[0]))
|
||||
@@ -1375,6 +1366,7 @@ static void fuse_ll_process(void *data, const char *buf, size_t len,
|
||||
struct fuse_in_header *in = (struct fuse_in_header *) buf;
|
||||
const void *inarg = buf + sizeof(struct fuse_in_header);
|
||||
struct fuse_req *req;
|
||||
int err;
|
||||
|
||||
if (f->debug)
|
||||
fprintf(stderr,
|
||||
@@ -1399,28 +1391,41 @@ static void fuse_ll_process(void *data, const char *buf, size_t len,
|
||||
list_init_req(req);
|
||||
fuse_mutex_init(&req->lock);
|
||||
|
||||
if (!f->got_init && in->opcode != FUSE_INIT)
|
||||
fuse_reply_err(req, EIO);
|
||||
else if (f->allow_root && in->uid != f->owner && in->uid != 0 &&
|
||||
err = EIO;
|
||||
if (!f->got_init) {
|
||||
enum fuse_opcode expected;
|
||||
|
||||
expected = f->cuse_data ? CUSE_INIT : FUSE_INIT;
|
||||
if (in->opcode != expected)
|
||||
goto reply_err;
|
||||
} else if (in->opcode == FUSE_INIT || in->opcode == CUSE_INIT)
|
||||
goto reply_err;
|
||||
|
||||
err = EACCES;
|
||||
if (f->allow_root && in->uid != f->owner && in->uid != 0 &&
|
||||
in->opcode != FUSE_INIT && in->opcode != FUSE_READ &&
|
||||
in->opcode != FUSE_WRITE && in->opcode != FUSE_FSYNC &&
|
||||
in->opcode != FUSE_RELEASE && in->opcode != FUSE_READDIR &&
|
||||
in->opcode != FUSE_FSYNCDIR && in->opcode != FUSE_RELEASEDIR) {
|
||||
fuse_reply_err(req, EACCES);
|
||||
} else if (in->opcode >= FUSE_MAXOP || !fuse_ll_ops[in->opcode].func)
|
||||
fuse_reply_err(req, ENOSYS);
|
||||
else {
|
||||
if (in->opcode != FUSE_INTERRUPT) {
|
||||
struct fuse_req *intr;
|
||||
pthread_mutex_lock(&f->lock);
|
||||
intr = check_interrupt(f, req);
|
||||
list_add_req(req, &f->list);
|
||||
pthread_mutex_unlock(&f->lock);
|
||||
if (intr)
|
||||
fuse_reply_err(intr, EAGAIN);
|
||||
}
|
||||
fuse_ll_ops[in->opcode].func(req, in->nodeid, inarg);
|
||||
in->opcode != FUSE_FSYNCDIR && in->opcode != FUSE_RELEASEDIR)
|
||||
goto reply_err;
|
||||
|
||||
err = ENOSYS;
|
||||
if (in->opcode >= FUSE_MAXOP || !fuse_ll_ops[in->opcode].func)
|
||||
goto reply_err;
|
||||
if (in->opcode != FUSE_INTERRUPT) {
|
||||
struct fuse_req *intr;
|
||||
pthread_mutex_lock(&f->lock);
|
||||
intr = check_interrupt(f, req);
|
||||
list_add_req(req, &f->list);
|
||||
pthread_mutex_unlock(&f->lock);
|
||||
if (intr)
|
||||
fuse_reply_err(intr, EAGAIN);
|
||||
}
|
||||
fuse_ll_ops[in->opcode].func(req, in->nodeid, inarg);
|
||||
return;
|
||||
|
||||
reply_err:
|
||||
fuse_reply_err(req, err);
|
||||
}
|
||||
|
||||
enum {
|
||||
@@ -1499,6 +1504,7 @@ static void fuse_ll_destroy(void *data)
|
||||
}
|
||||
|
||||
pthread_mutex_destroy(&f->lock);
|
||||
free(f->cuse_data);
|
||||
free(f);
|
||||
}
|
||||
|
||||
|
||||
+1
-11
@@ -6,7 +6,7 @@
|
||||
See the file COPYING.LIB
|
||||
*/
|
||||
|
||||
#include "fuse_lowlevel.h"
|
||||
#include "fuse_i.h"
|
||||
#include "fuse_misc.h"
|
||||
#include "fuse_common_compat.h"
|
||||
#include "fuse_lowlevel_compat.h"
|
||||
@@ -17,16 +17,6 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
struct fuse_session {
|
||||
struct fuse_session_ops op;
|
||||
|
||||
void *data;
|
||||
|
||||
volatile int exited;
|
||||
|
||||
struct fuse_chan *ch;
|
||||
};
|
||||
|
||||
struct fuse_chan {
|
||||
struct fuse_chan_ops op;
|
||||
|
||||
|
||||
@@ -160,6 +160,10 @@ FUSE_2.7.5 {
|
||||
|
||||
FUSE_2.8 {
|
||||
global:
|
||||
cuse_lowlevel_new;
|
||||
cuse_lowlevel_main;
|
||||
cuse_lowlevel_setup;
|
||||
cuse_lowlevel_teardown;
|
||||
fuse_fs_ioctl;
|
||||
fuse_fs_poll;
|
||||
fuse_lowlevel_notify_poll;
|
||||
@@ -167,6 +171,7 @@ FUSE_2.8 {
|
||||
fuse_opt_add_opt_escaped;
|
||||
fuse_pollhandle_destroy;
|
||||
fuse_reply_ioctl;
|
||||
fuse_reply_ioctl_iov;
|
||||
fuse_reply_ioctl_retry;
|
||||
fuse_reply_poll;
|
||||
|
||||
|
||||
+8
-8
@@ -235,14 +235,14 @@ void fuse_unmount(const char *mountpoint, struct fuse_chan *ch)
|
||||
fuse_unmount_common(mountpoint, ch);
|
||||
}
|
||||
|
||||
static struct fuse *fuse_setup_common(int argc, char *argv[],
|
||||
const struct fuse_operations *op,
|
||||
size_t op_size,
|
||||
char **mountpoint,
|
||||
int *multithreaded,
|
||||
int *fd,
|
||||
void *user_data,
|
||||
int compat)
|
||||
struct fuse *fuse_setup_common(int argc, char *argv[],
|
||||
const struct fuse_operations *op,
|
||||
size_t op_size,
|
||||
char **mountpoint,
|
||||
int *multithreaded,
|
||||
int *fd,
|
||||
void *user_data,
|
||||
int compat)
|
||||
{
|
||||
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
|
||||
struct fuse_chan *ch;
|
||||
|
||||
Reference in New Issue
Block a user