diff options
author | Miklos Szeredi <miklos@szeredi.hu> | 2009-06-18 11:11:54 +0000 |
---|---|---|
committer | Miklos Szeredi <miklos@szeredi.hu> | 2009-06-18 11:11:54 +0000 |
commit | ae9bfde712697205ac8809edc431cb7c0bdd484f (patch) | |
tree | 6f05932e39f7b1bfb44452bb09aecaa2826e4f0b /lib | |
parent | bc53eddb2f76be3e134aa5ed1814254aa289f898 (diff) | |
download | android_external_fuse-ae9bfde712697205ac8809edc431cb7c0bdd484f.tar.gz android_external_fuse-ae9bfde712697205ac8809edc431cb7c0bdd484f.tar.bz2 android_external_fuse-ae9bfde712697205ac8809edc431cb7c0bdd484f.zip |
CUSE patches from Tejun Heo
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Makefile.am | 1 | ||||
-rw-r--r-- | lib/fuse.c | 28 | ||||
-rw-r--r-- | lib/fuse_i.h | 69 | ||||
-rw-r--r-- | lib/fuse_lowlevel.c | 136 | ||||
-rw-r--r-- | lib/fuse_session.c | 12 | ||||
-rw-r--r-- | lib/fuse_versionscript | 5 | ||||
-rw-r--r-- | lib/helper.c | 16 |
7 files changed, 163 insertions, 104 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am index 0694980..7fce149 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -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) \ @@ -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, diff --git a/lib/fuse_i.h b/lib/fuse_i.h index ec6e5d6..9bc1d70 100644 --- a/lib/fuse_i.h +++ b/lib/fuse_i.h @@ -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); diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index 63a0668..e3b5d5d 100644 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -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); } diff --git a/lib/fuse_session.c b/lib/fuse_session.c index 5efedd9..7df4795 100644 --- a/lib/fuse_session.c +++ b/lib/fuse_session.c @@ -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; diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript index f2608a8..4cd09aa 100644 --- a/lib/fuse_versionscript +++ b/lib/fuse_versionscript @@ -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; diff --git a/lib/helper.c b/lib/helper.c index d1cd075..3d0db4a 100644 --- a/lib/helper.c +++ b/lib/helper.c @@ -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; |