diff options
Diffstat (limited to 'lib/helper.c')
-rw-r--r-- | lib/helper.c | 154 |
1 files changed, 154 insertions, 0 deletions
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); +} + |