aboutsummaryrefslogtreecommitdiff
path: root/lib/fuse.c
diff options
context:
space:
mode:
authorGravatar Fabrice Bauzac <fbauzac@amadeus.com>2013-09-23 16:57:50 +0200
committerGravatar Miklos Szeredi <mszeredi@suse.cz>2014-02-04 18:22:23 +0100
commitd4e294b7995a921fbc7691cccb7dd577bba52ba7 (patch)
tree82f81ff98586575011cbdd123af45b4053a7e831 /lib/fuse.c
parent8bb62a632caa4269bb6436cae67307404882b936 (diff)
fuse: use dlsym() instead of relying on ld.so constructor functions
Diffstat (limited to 'lib/fuse.c')
-rw-r--r--lib/fuse.c122
1 files changed, 79 insertions, 43 deletions
diff --git a/lib/fuse.c b/lib/fuse.c
index 7508c54..3f8e601 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -208,55 +208,90 @@ struct fuse_context_i {
fuse_req_t req;
};
+/* Defined by FUSE_REGISTER_MODULE() in lib/modules/subdir.c and iconv.c. */
+extern fuse_module_factory_t fuse_module_subdir_factory;
+extern fuse_module_factory_t fuse_module_iconv_factory;
+
static pthread_key_t fuse_context_key;
static pthread_mutex_t fuse_context_lock = PTHREAD_MUTEX_INITIALIZER;
static int fuse_context_ref;
-static struct fusemod_so *fuse_current_so;
-static struct fuse_module *fuse_modules;
+static struct fuse_module *fuse_modules = NULL;
-static int fuse_load_so_name(const char *soname)
+static int fuse_register_module(const char *name,
+ fuse_module_factory_t factory,
+ struct fusemod_so *so)
{
- struct fusemod_so *so;
+ struct fuse_module *mod;
- so = calloc(1, sizeof(struct fusemod_so));
- if (!so) {
- fprintf(stderr, "fuse: memory allocation failed\n");
+ mod = calloc(1, sizeof(struct fuse_module));
+ if (!mod) {
+ fprintf(stderr, "fuse: failed to allocate module\n");
return -1;
}
-
- fuse_current_so = so;
- so->handle = dlopen(soname, RTLD_NOW);
- fuse_current_so = NULL;
- if (!so->handle) {
- fprintf(stderr, "fuse: %s\n", dlerror());
- goto err;
- }
- if (!so->ctr) {
- fprintf(stderr, "fuse: %s did not register any modules\n",
- soname);
- goto err;
+ mod->name = strdup(name);
+ if (!mod->name) {
+ fprintf(stderr, "fuse: failed to allocate module name\n");
+ free(mod);
+ return -1;
}
- return 0;
+ mod->factory = factory;
+ mod->ctr = 0;
+ mod->so = so;
+ if (mod->so)
+ mod->so->ctr++;
+ mod->next = fuse_modules;
+ fuse_modules = mod;
-err:
- if (so->handle)
- dlclose(so->handle);
- free(so);
- return -1;
+ return 0;
}
+
static int fuse_load_so_module(const char *module)
{
- int res;
- char *soname = malloc(strlen(module) + 64);
- if (!soname) {
+ int ret = -1;
+ char *tmp;
+ struct fusemod_so *so;
+ fuse_module_factory_t factory;
+
+ tmp = malloc(strlen(module) + 64);
+ if (!tmp) {
fprintf(stderr, "fuse: memory allocation failed\n");
return -1;
}
- sprintf(soname, "libfusemod_%s.so", module);
- res = fuse_load_so_name(soname);
- free(soname);
- return res;
+ sprintf(tmp, "libfusemod_%s.so", module);
+ so = calloc(1, sizeof(struct fusemod_so));
+ if (!so) {
+ fprintf(stderr, "fuse: failed to allocate module so\n");
+ goto out;
+ }
+
+ so->handle = dlopen(tmp, RTLD_NOW);
+ if (so->handle == NULL) {
+ fprintf(stderr, "fuse: dlopen(%s) failed: %s\n",
+ tmp, dlerror());
+ goto out_free_so;
+ }
+
+ sprintf(tmp, "fuse_module_%s_factory", module);
+ factory = dlsym(so->handle, tmp);
+ if (factory == NULL) {
+ fprintf(stderr, "fuse: symbol <%s> not found in module: %s\n",
+ tmp, dlerror());
+ goto out_dlclose;
+ }
+ ret = fuse_register_module(module, factory, so);
+ if (ret)
+ goto out_dlclose;
+
+out:
+ free(tmp);
+ return ret;
+
+out_dlclose:
+ dlclose(so->handle);
+out_free_so:
+ free(so);
+ goto out;
}
static struct fuse_module *fuse_find_module(const char *module)
@@ -4342,6 +4377,18 @@ struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args,
struct fuse_fs *fs;
struct fuse_lowlevel_ops llop = fuse_path_ops;
+ pthread_mutex_lock(&fuse_context_lock);
+ static int builtin_modules_registered = 0;
+ /* Have the builtin modules already been registered? */
+ if (builtin_modules_registered == 0) {
+ /* If not, register them. */
+ fuse_register_module("subdir", fuse_module_subdir_factory, NULL);
+ fuse_register_module("iconv", fuse_module_iconv_factory, NULL);
+ builtin_modules_registered= 1;
+ }
+ pthread_mutex_unlock(&fuse_context_lock);
+
+
if (fuse_create_context_key() == -1)
goto out;
@@ -4522,14 +4569,3 @@ void fuse_destroy(struct fuse *f)
fuse_delete_context_key();
}
-/* called with fuse_context_lock held or during initialization (before
- main() has been called) */
-void fuse_register_module(struct fuse_module *mod)
-{
- mod->ctr = 0;
- mod->so = fuse_current_so;
- if (mod->so)
- mod->so->ctr++;
- mod->next = fuse_modules;
- fuse_modules = mod;
-}