diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Makefile.am | 1 | ||||
-rw-r--r-- | lib/fuse.c | 4 | ||||
-rw-r--r-- | lib/helper.c | 154 |
3 files changed, 158 insertions, 1 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am index 7f289f7..5ecee0b 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -5,4 +5,5 @@ lib_LIBRARIES = libfuse.a libfuse_a_SOURCES = \ fuse.c \ fuse_mt.c \ + helper.c \ fuse_i.h @@ -17,6 +17,8 @@ #define FUSE_MAX_PATH 4096 +#define FUSE_KERNEL_VERSION_ENV "_FUSE_KERNEL_VERSION" + static struct node *__get_node(struct fuse *f, fino_t ino) { size_t hash = ino % f->ino_table_size; @@ -891,7 +893,7 @@ struct fuse *fuse_new(int fd, int flags) struct fuse *f; struct node *root; char verstr[128]; - char *realver = getenv("FUSE_KERNEL_VERSION"); + char *realver = getenv(FUSE_KERNEL_VERSION_ENV); if(realver != NULL) { sprintf(verstr, "%i", FUSE_KERNEL_VERSION); diff --git a/lib/helper.c b/lib/helper.c new file mode 100644 index 0000000..f4a8a16 --- /dev/null +++ b/lib/helper.c @@ -0,0 +1,154 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001 Miklos Szeredi (mszeredi@inf.bme.hu) + + This program can be distributed under the terms of the GNU GPL. + See the file COPYING. +*/ + +#include "fuse.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <limits.h> +#include <signal.h> +#include <errno.h> + +#define FUSE_MOUNTED_ENV "_FUSE_MOUNTED" +#define FUSE_UMOUNT_CMD_ENV "_FUSE_UNMOUNT_CMD" + +static void usage(char *progname) +{ + fprintf(stderr, + "usage: %s mountpoint [options] \n" + "Options:\n" + " -d enable debug output\n" + " -s disable multithreaded operation\n" + " -h print help\n", + progname); + exit(1); +} + +static void fuse_unmount() +{ + close(0); + system(getenv(FUSE_UMOUNT_CMD_ENV)); +} + +static int fuse_mount(int *argcp, char **argv) +{ + char *isreexec = getenv(FUSE_MOUNTED_ENV); + + if(isreexec == NULL) { + int i; + int argc = *argcp; + char *mountprog = "fusermount"; + char **newargv = (char **) malloc((1 + argc + 1) * sizeof(char *)); + + if(argc < 2 || argv[1][0] == '-') + usage(argv[0]); + + /* oldargs: "PROG MOUNTPOINT ARGS..." + newargs: "fusermount MOUNTPOINT PROG ARGS..." */ + + newargv[0] = mountprog; + newargv[1] = argv[1]; + newargv[2] = argv[0]; + for(i = 2; i < argc; i++) + newargv[i+1] = argv[i]; + newargv[i+1] = NULL; + + execvp(mountprog, newargv); + fprintf(stderr, "fuse: failed to exec %s: %s\n", mountprog, + strerror(errno)); + return -1; + } + unsetenv(FUSE_MOUNTED_ENV); + + /* The actual file descriptor is stdin */ + return 0; +} + + +static void exit_handler() +{ + exit(0); +} + +static void set_signal_handlers() +{ + struct sigaction sa; + + sa.sa_handler = exit_handler; + sigemptyset(&(sa.sa_mask)); + sa.sa_flags = 0; + + if (sigaction(SIGHUP, &sa, NULL) == -1 || + sigaction(SIGINT, &sa, NULL) == -1 || + sigaction(SIGTERM, &sa, NULL) == -1) { + + perror("Cannot set exit signal handlers"); + exit(1); + } + + sa.sa_handler = SIG_IGN; + + if(sigaction(SIGPIPE, &sa, NULL) == -1) { + perror("Cannot set ignored signals"); + exit(1); + } +} + +void fuse_main(int argc, char *argv[], const struct fuse_operations *op) +{ + int fd; + int argctr; + int flags; + int multithreaded; + struct fuse *fuse; + + fd = fuse_mount(&argc, argv); + if(fd == -1) + exit(1); + + atexit(fuse_unmount); + set_signal_handlers(); + + argctr = 1; + flags = 0; + multithreaded = 1; + for(; argctr < argc && argv[argctr][0] == '-'; argctr ++) { + switch(argv[argctr][1]) { + case 'd': + flags |= FUSE_DEBUG; + break; + + case 's': + multithreaded = 0; + break; + + case 'h': + usage(argv[0]); + break; + + default: + fprintf(stderr, "invalid option: %s\n", argv[argctr]); + exit(1); + } + } + if(argctr != argc) { + fprintf(stderr, "missing or surplus argument\n"); + exit(1); + } + + fuse = fuse_new(fd, flags); + fuse_set_operations(fuse, op); + + if(multithreaded) + fuse_loop_mt(fuse); + else + fuse_loop(fuse); +} + |