aboutsummaryrefslogtreecommitdiff
path: root/lib/fuse.c
diff options
context:
space:
mode:
authorGravatar Miklos Szeredi <mszeredi@suse.cz>2013-02-05 13:36:06 +0100
committerGravatar Miklos Szeredi <mszeredi@suse.cz>2013-02-05 13:36:06 +0100
commiteca08beaf5a7b4121da27c2a927a6ecbb08a74bf (patch)
tree5aee2b83578d489d3d7ac8d2e759ff5b1ba43894 /lib/fuse.c
parent95e1a99472b11560d98046fc2427788be0c14412 (diff)
libfuse: fix fuse_get_context() in non fuse threads
fuse_interrupted(), fuse_get_context(), etc... crashed in non-fuse threads. Instead return false, NULL or error depending on the function. Reported by Michael Berlin
Diffstat (limited to 'lib/fuse.c')
-rw-r--r--lib/fuse.c48
1 files changed, 30 insertions, 18 deletions
diff --git a/lib/fuse.c b/lib/fuse.c
index 7b6ce99..6e3c431 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -2368,9 +2368,12 @@ static int lookup_path(struct fuse *f, fuse_ino_t nodeid,
static struct fuse_context_i *fuse_get_context_internal(void)
{
- struct fuse_context_i *c;
+ return (struct fuse_context_i *) pthread_getspecific(fuse_context_key);
+}
- c = (struct fuse_context_i *) pthread_getspecific(fuse_context_key);
+static struct fuse_context_i *fuse_create_context(struct fuse *f)
+{
+ struct fuse_context_i *c = fuse_get_context_internal();
if (c == NULL) {
c = (struct fuse_context_i *)
calloc(1, sizeof(struct fuse_context_i));
@@ -2383,7 +2386,11 @@ static struct fuse_context_i *fuse_get_context_internal(void)
abort();
}
pthread_setspecific(fuse_context_key, c);
+ } else {
+ memset(c, 0, sizeof(*c));
}
+ c->ctx.fuse = f;
+
return c;
}
@@ -2423,10 +2430,9 @@ static void fuse_delete_context_key(void)
static struct fuse *req_fuse_prepare(fuse_req_t req)
{
- struct fuse_context_i *c = fuse_get_context_internal();
+ struct fuse_context_i *c = fuse_create_context(req_fuse(req));
const struct fuse_ctx *ctx = fuse_req_ctx(req);
c->req = req;
- c->ctx.fuse = req_fuse(req);
c->ctx.uid = ctx->uid;
c->ctx.gid = ctx->gid;
c->ctx.pid = ctx->pid;
@@ -2470,10 +2476,8 @@ void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn)
static void fuse_lib_init(void *data, struct fuse_conn_info *conn)
{
struct fuse *f = (struct fuse *) data;
- struct fuse_context_i *c = fuse_get_context_internal();
- memset(c, 0, sizeof(*c));
- c->ctx.fuse = f;
+ fuse_create_context(f);
conn->want |= FUSE_CAP_EXPORT_SUPPORT;
fuse_fs_init(f->fs, conn);
}
@@ -2491,10 +2495,8 @@ void fuse_fs_destroy(struct fuse_fs *fs)
static void fuse_lib_destroy(void *data)
{
struct fuse *f = (struct fuse *) data;
- struct fuse_context_i *c = fuse_get_context_internal();
- memset(c, 0, sizeof(*c));
- c->ctx.fuse = f;
+ fuse_create_context(f);
fuse_fs_destroy(f->fs);
f->fs = NULL;
}
@@ -4189,18 +4191,31 @@ void fuse_exit(struct fuse *f)
struct fuse_context *fuse_get_context(void)
{
- return &fuse_get_context_internal()->ctx;
+ struct fuse_context_i *c = fuse_get_context_internal();
+
+ if (c)
+ return &c->ctx;
+ else
+ return NULL;
}
int fuse_getgroups(int size, gid_t list[])
{
- fuse_req_t req = fuse_get_context_internal()->req;
- return fuse_req_getgroups(req, size, list);
+ struct fuse_context_i *c = fuse_get_context_internal();
+ if (!c)
+ return -EINVAL;
+
+ return fuse_req_getgroups(c->req, size, list);
}
int fuse_interrupted(void)
{
- return fuse_req_interrupted(fuse_get_context_internal()->req);
+ struct fuse_context_i *c = fuse_get_context_internal();
+
+ if (c)
+ return fuse_req_interrupted(c->req);
+ else
+ return 0;
}
void fuse_set_getcontext_func(struct fuse_context *(*func)(void))
@@ -4589,10 +4604,7 @@ void fuse_destroy(struct fuse *f)
fuse_restore_intr_signal(f->conf.intr_signal);
if (f->fs) {
- struct fuse_context_i *c = fuse_get_context_internal();
-
- memset(c, 0, sizeof(*c));
- c->ctx.fuse = f;
+ fuse_create_context(f);
for (i = 0; i < f->id_table.size; i++) {
struct node *node;