aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2009-06-18 11:11:54 +0000
committerMiklos Szeredi <miklos@szeredi.hu>2009-06-18 11:11:54 +0000
commitae9bfde712697205ac8809edc431cb7c0bdd484f (patch)
tree6f05932e39f7b1bfb44452bb09aecaa2826e4f0b /lib
parentbc53eddb2f76be3e134aa5ed1814254aa289f898 (diff)
downloadandroid_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.am1
-rw-r--r--lib/fuse.c28
-rw-r--r--lib/fuse_i.h69
-rw-r--r--lib/fuse_lowlevel.c136
-rw-r--r--lib/fuse_session.c12
-rw-r--r--lib/fuse_versionscript5
-rw-r--r--lib/helper.c16
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) \
diff --git a/lib/fuse.c b/lib/fuse.c
index 8c27cd3..f7e78a8 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -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;