aboutsummaryrefslogtreecommitdiffstats
path: root/lib/helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/helper.c')
-rw-r--r--lib/helper.c143
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);
}