diff options
Diffstat (limited to 'lib/helper.c')
-rw-r--r-- | lib/helper.c | 143 |
1 files changed, 15 insertions, 128 deletions
diff --git a/lib/helper.c b/lib/helper.c index 522b377..d3b8b1c 100644 --- a/lib/helper.c +++ b/lib/helper.c @@ -10,21 +10,15 @@ #include <stdio.h> #include <stdlib.h> -#include <string.h> #include <unistd.h> +#include <string.h> #include <limits.h> #include <signal.h> -#include <errno.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <fcntl.h> -#include <sys/wait.h> #define FUSE_MOUNTED_ENV "_FUSE_MOUNTED" #define FUSE_UMOUNT_CMD_ENV "_FUSE_UNMOUNT_CMD" -#define FUSE_COMMFD_ENV "_FUSE_COMMFD" -#define FUSERMOUNT_PROG "fusermount" +static struct fuse *fuse; static void usage(char *progname) { @@ -38,125 +32,10 @@ static void usage(char *progname) exit(1); } -static char umount_cmd[1024]; -static int fuse_fd; - -static void fuse_unmount() -{ - close(fuse_fd); - if(umount_cmd[0] != '\0') - system(umount_cmd); -} - -/* return value: - * >= 0 => fd - * -1 => error - */ -static int receive_fd(int fd) -{ - struct msghdr msg; - struct iovec iov; - char buf[1]; - int rv; - int connfd = -1; - char ccmsg[CMSG_SPACE(sizeof(connfd))]; - struct cmsghdr *cmsg; - - iov.iov_base = buf; - iov.iov_len = 1; - - msg.msg_name = 0; - msg.msg_namelen = 0; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - /* old BSD implementations should use msg_accrights instead of - * msg_control; the interface is different. */ - msg.msg_control = ccmsg; - msg.msg_controllen = sizeof(ccmsg); - - while(((rv = recvmsg(fd, &msg, 0)) == -1) && errno == EINTR); - if (rv == -1) { - perror("recvmsg"); - return -1; - } - if(!rv) { - /* EOF */ - fprintf(stderr, "got EOF\n"); - return -1; - } - - cmsg = CMSG_FIRSTHDR(&msg); - if (!cmsg->cmsg_type == SCM_RIGHTS) { - fprintf(stderr, "got control message of unknown type %d\n", - cmsg->cmsg_type); - return -1; - } - return *(int*)CMSG_DATA(cmsg); -} - -int fuse_mount(const char *mountpoint, const char *args[]) -{ - const char *mountprog = FUSERMOUNT_PROG; - int fds[2], pid; - int res; - int rv; - - snprintf(umount_cmd, sizeof(umount_cmd) - 1, "%s -u %s", mountprog, - mountpoint); - - res = socketpair(PF_UNIX, SOCK_STREAM, 0, fds); - if(res == -1) { - perror("fuse: socketpair() failed"); - return -1; - } - - pid = fork(); - if(pid == -1) { - perror("fuse: fork() failed"); - close(fds[0]); - close(fds[1]); - return -1; - } - - if(pid == 0) { - char env[10]; - char **newargv; - int numargs = 0; - int actr; - int i; - - if(args != NULL) - while(args[numargs] != NULL) - numargs ++; - - newargv = (char **) malloc((1 + numargs + 2) * sizeof(char *)); - actr = 0; - newargv[actr++] = strdup(mountprog); - for(i = 0; i < numargs; i++) - newargv[actr++] = strdup(args[i]); - newargv[actr++] = strdup(mountpoint); - newargv[actr++] = NULL; - - close(fds[1]); - fcntl(fds[0], F_SETFD, 0); - snprintf(env, sizeof(env), "%i", fds[0]); - setenv(FUSE_COMMFD_ENV, env, 1); - execvp(mountprog, newargv); - perror("fuse: failed to exec fusermount"); - exit(1); - } - - close(fds[0]); - rv = receive_fd(fds[1]); - close(fds[1]); - waitpid(pid, NULL, 0); /* bury zombie */ - - return rv; -} - static void exit_handler() { - exit(0); + if(fuse != NULL) + fuse_exit(fuse); } static void set_signal_handlers() @@ -188,14 +67,17 @@ void fuse_main(int argc, char *argv[], const struct fuse_operations *op) int argctr = 1; int flags; int multithreaded; - struct fuse *fuse; char *isreexec = getenv(FUSE_MOUNTED_ENV); + int fuse_fd; + char *fuse_mountpoint = NULL; + char umount_cmd[1024] = ""; if(isreexec == NULL) { if(argc < 2 || argv[1][0] == '-') usage(argv[0]); - fuse_fd = fuse_mount(argv[1], NULL); + fuse_mountpoint = strdup(argv[1]); + fuse_fd = fuse_mount(fuse_mountpoint, NULL); if(fuse_fd == -1) exit(1); @@ -217,7 +99,6 @@ void fuse_main(int argc, char *argv[], const struct fuse_operations *op) strncpy(umount_cmd, tmpstr, sizeof(umount_cmd) - 1); } - atexit(fuse_unmount); set_signal_handlers(); flags = 0; @@ -252,5 +133,11 @@ void fuse_main(int argc, char *argv[], const struct fuse_operations *op) fuse_loop_mt(fuse); else fuse_loop(fuse); + + close(fuse_fd); + if(fuse_mountpoint != NULL) + fuse_unmount(fuse_mountpoint); + else if(umount_cmd[0] != '\0') + system(umount_cmd); } |