use fuse_mount in fuse_main
authorMiklos Szeredi <miklos@szeredi.hu>
Fri, 25 Oct 2002 11:40:14 +0000 (11:40 +0000)
committerMiklos Szeredi <miklos@szeredi.hu>
Fri, 25 Oct 2002 11:40:14 +0000 (11:40 +0000)
ChangeLog
include/fuse.h
lib/helper.c
makeconf.sh
util/Makefile.am
util/fuse_ioslave.c [deleted file]
util/fusermount.c

index 8c01735576e2796ff4156f09f5ccbe0a7504a946..e9a14af42e0e43bb85bfd4a0d1f20968574dfc09 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2002-10-25  Miklos Szeredi <mszeredi@inf.bme.hu>
+
+       * Use Mark Glines' fd passing method for default operation instead
+       of old reexec
+
 2002-10-22  Miklos Szeredi <mszeredi@inf.bme.hu>
 
        * fix "Stale NFS file handle" bug caused by changes in 2.4.19
index 78cd877e767deb1c764623edee97d6affd6f6948..6a3ed3a364c867860f7ce42c2804e97f7946a7fe 100644 (file)
@@ -116,10 +116,11 @@ extern "C" {
  * fuse_new()
  *
  * @param mountpoint the mount point path
- * @param mount arguments (passed to the fusermount program)
+ * @param args array of arguments to be passed to fusermount (NULL
+ *        terminated).  Can be NULL if no arguments are needed.
  * @return the control file descriptor on success, -1 on failure
  */
-int fuse_mount(const char *mountpoint, const char *mount_args);
+int fuse_mount(const char *mountpoint, const char *args[]);
 
 /**
  * Create a new FUSE filesystem.
index f523f99f8a16a631b9d4bbe679cb46631d1cb51f..559e99249b0a54c7ca022fda76f38f91b5283bde 100644 (file)
 #include <fcntl.h>
 #include <sys/wait.h>
 
-#define FUSE_MOUNTED_ENV     "_FUSE_MOUNTED"
-#define FUSE_UMOUNT_CMD_ENV  "_FUSE_UNMOUNT_CMD"
+#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 void usage(char *progname)
 {
@@ -35,51 +38,22 @@ static void usage(char *progname)
     exit(1);
 }
 
-static void fuse_unmount()
-{
-    close(0);
-    system(getenv(FUSE_UMOUNT_CMD_ENV));
-}
+static char umount_cmd[1024];
+static int fuse_fd;
 
-static int fuse_mount_obsolete(int *argcp, char **argv)
+static void fuse_unmount()
 {
-    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;
+    close(fuse_fd);
+    if(umount_cmd[0] != '\0')
+        system(umount_cmd);
 }
 
 /* return value:
  * >= 0  => fd
  * -1    => error
  */
-int receive_fd(int fd) {
+static int receive_fd(int fd)
+{
     struct msghdr msg;
     struct iovec iov;
     char buf[1];
@@ -120,46 +94,63 @@ int receive_fd(int fd) {
     return *(int*)CMSG_DATA(cmsg);
 }
 
-int fuse_mount(const char *mountpoint, const char *mount_args)
+int fuse_mount(const char *mountpoint, const char *args[])
 {
+    const char *mountprog = FUSERMOUNT_PROG;
     int fds[2], pid;
-    int rv, fd;
-    char env[10];
+    int res;
+    int rv;
+
+    snprintf(umount_cmd, sizeof(umount_cmd) - 1, "%s -u %s", mountprog,
+             mountpoint);
     
-    /* FIXME: parse mount_args (or just pass it to fusermount ???) */
-    mount_args = mount_args;
-
-    /* make sure the socket fds are greater than 0 */
-    fd = open("/dev/null",O_RDONLY); 
-    rv = socketpair(PF_UNIX,SOCK_STREAM,0,fds);
-    close(fd);
-    if(rv) {
-        fprintf(stderr,"fuse: failed to socketpair()\n");
-        close(fd);
+    res = socketpair(PF_UNIX, SOCK_STREAM, 0, fds);
+    if(res == -1) {
+        perror("fuse: socketpair() failed");
         return -1;
     }
+
     pid = fork();
-    if(pid < 0) {
-        fprintf(stderr,"fuse: failed to fork()\n");
+    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_IOSLAVE_FD",env,1);
-        execlp("fusermount","fusermount",mountpoint,"fuse_ioslave",NULL);
-        fprintf(stderr,"fuse: failed to exec fusermount\n");
+        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);
     }
 
-    fd = fds[1];
     close(fds[0]);
-    rv = receive_fd(fd);
-    close(fd);
-    waitpid(pid,NULL,0); /* bury zombie */
+    rv = receive_fd(fds[1]);
+    close(fds[1]);
+    waitpid(pid, NULL, 0); /* bury zombie */
+
     return rv;
 }
 
@@ -194,20 +185,41 @@ static void set_signal_handlers()
 
 void fuse_main(int argc, char *argv[], const struct fuse_operations *op)
 {
-    int fd;
-    int argctr;
+    int argctr = 1;
     int flags;
     int multithreaded;
     struct fuse *fuse;
+    char *isreexec = getenv(FUSE_MOUNTED_ENV);
 
-    fd = fuse_mount_obsolete(&argc, argv);
-    if(fd == -1)
-        exit(1);
+    if(isreexec == NULL) {
+        if(argc < 2 || argv[1][0] == '-')
+            usage(argv[0]);
+
+        fuse_fd = fuse_mount(argv[1], NULL);
+        if(fuse_fd == -1)
+            exit(1);
+
+        argctr++;
+    }
+    else {
+        char *tmpstr;
+
+        /* Old (obsolescent) way of doing the mount: 
+           
+             fusermount [options] mountpoint [program [args ...]]
+
+           fusermount execs this program and passes the control file
+           descriptor dup()-ed to stdin */
+        fuse_fd = 0;
+        
+        tmpstr = getenv(FUSE_UMOUNT_CMD_ENV);
+        if(tmpstr != NULL)
+            strncpy(umount_cmd, tmpstr, sizeof(umount_cmd) - 1);
+    }
 
     atexit(fuse_unmount);
     set_signal_handlers();
 
-    argctr = 1;
     flags = 0;
     multithreaded = 1;
     for(; argctr < argc && argv[argctr][0] == '-'; argctr ++) {
@@ -234,7 +246,7 @@ void fuse_main(int argc, char *argv[], const struct fuse_operations *op)
         exit(1);
     }
 
-    fuse = fuse_new(fd, flags, op);
+    fuse = fuse_new(fuse_fd, flags, op);
 
     if(multithreaded)
         fuse_loop_mt(fuse);
index 2c97050cdceccb2dc46b0519af37f6a3a308a239..8cd29ad9419020860ffee86fad92d8b7d9d4eed6 100755 (executable)
@@ -1,6 +1,12 @@
 #! /bin/sh
 
+echo Running aclocal...
 aclocal
+echo Running autoheader...
 autoheader
+echo Running autoconf...
 autoconf
+echo Running automake...
 automake -a -c
+rm -f config.cache config.status
+echo "To compile run './configure', and then 'make'."
index 0e4434f2d7bf58c3775043c3cf6bbd473a28dcb2..48f99576eec4187ee3dc203ca459cf55125d80fd 100644 (file)
@@ -1,9 +1,8 @@
 ## Process this file with automake to produce Makefile.in
 
-bin_PROGRAMS = fusermount fuse_ioslave
+bin_PROGRAMS = fusermount
 
 fusermount_SOURCES = fusermount.c
-fuse_ioslave_SOURCES = fuse_ioslave.c
 
 install-exec-hook:
        -chown root $(DESTDIR)$(bindir)/fusermount
diff --git a/util/fuse_ioslave.c b/util/fuse_ioslave.c
deleted file mode 100644 (file)
index df7c66d..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-#include <stdio.h>                 /* fprintf */
-#include <errno.h>                 /* errno */
-#include <string.h>                /* strerror */
-#include <unistd.h>                /* read,write,close */
-#include <stdlib.h>                /* getenv,strtol */
-#include <sys/select.h>            /* select */
-#include <sys/socket.h>            /* send, recv */
-#include <sys/un.h>                /* struct sockaddr_un */
-#define BUFSIZE (2<<16)
-#undef IOSLAVE_DEBUG
-char *scratch;
-
-/* return values:
- * 0  => success
- * -1 => error condition
- */
-int send_fd(int sock_fd, int send_fd) {
-    int retval;
-    struct msghdr msg;
-    struct cmsghdr *p_cmsg;
-    struct iovec vec;
-    char cmsgbuf[CMSG_SPACE(sizeof(send_fd))];
-    int *p_fds;
-    char sendchar = 0;
-    msg.msg_control = cmsgbuf;
-    msg.msg_controllen = sizeof(cmsgbuf);
-    p_cmsg = CMSG_FIRSTHDR(&msg);
-    p_cmsg->cmsg_level = SOL_SOCKET;
-    p_cmsg->cmsg_type = SCM_RIGHTS;
-    p_cmsg->cmsg_len = CMSG_LEN(sizeof(send_fd));
-    p_fds = (int *) CMSG_DATA(p_cmsg);
-    *p_fds = send_fd;
-    msg.msg_controllen = p_cmsg->cmsg_len;
-    msg.msg_name = NULL;
-    msg.msg_namelen = 0;
-    msg.msg_iov = &vec;
-    msg.msg_iovlen = 1;
-    msg.msg_flags = 0;
-    /* "To pass file descriptors or credentials you need to send/read at
-     * least one byte" (man 7 unix)
-     */
-    vec.iov_base = &sendchar;
-    vec.iov_len = sizeof(sendchar);
-    while((retval = sendmsg(sock_fd, &msg, 0)) == -1 && errno == EINTR);
-    if (retval != 1) {
-        perror("sendmsg");
-        return -1;
-    }
-    return 0;
-}
-
-int main() {
-    char *env = getenv("_FUSE_IOSLAVE_FD");
-    int fd;
-    if (!env)
-        exit(fprintf(stderr, "fuse_ioslave: do not run me directly\n"));
-    fd = strtol(env, NULL, 0);
-    if(send_fd(fd, 0) == -1)
-       fprintf(stderr,"failed to send fd\n");
-    return 0;
-}
index b3f46cfd407ef0d229f861fc37479454bc361e05..ac464d217843ab047bc99541af03e612e640f68d 100644 (file)
@@ -29,6 +29,8 @@
 #include <sys/stat.h>
 #include <sys/mount.h>
 #include <sys/fsuid.h>
+#include <sys/socket.h>
+#include <sys/un.h>
 #include <linux/fuse.h>
 
 #define CHECK_PERMISSION 1
@@ -42,6 +44,7 @@
 #define FUSE_MOUNTED_ENV        "_FUSE_MOUNTED"
 #define FUSE_UMOUNT_CMD_ENV     "_FUSE_UNMOUNT_CMD"
 #define FUSE_KERNEL_VERSION_ENV "_FUSE_KERNEL_VERSION"
+#define FUSE_COMMFD_ENV         "_FUSE_COMMFD"
 
 const char *progname;
 
@@ -395,6 +398,42 @@ static char *resolve_path(const char *orig, int unmount)
     return strdup(buf);
 }
 
+static int send_fd(int sock_fd, int fd) 
+{
+    int retval;
+    struct msghdr msg;
+    struct cmsghdr *p_cmsg;
+    struct iovec vec;
+    char cmsgbuf[CMSG_SPACE(sizeof(fd))];
+    int *p_fds;
+    char sendchar = 0;
+
+    msg.msg_control = cmsgbuf;
+    msg.msg_controllen = sizeof(cmsgbuf);
+    p_cmsg = CMSG_FIRSTHDR(&msg);
+    p_cmsg->cmsg_level = SOL_SOCKET;
+    p_cmsg->cmsg_type = SCM_RIGHTS;
+    p_cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
+    p_fds = (int *) CMSG_DATA(p_cmsg);
+    *p_fds = fd;
+    msg.msg_controllen = p_cmsg->cmsg_len;
+    msg.msg_name = NULL;
+    msg.msg_namelen = 0;
+    msg.msg_iov = &vec;
+    msg.msg_iovlen = 1;
+    msg.msg_flags = 0;
+    /* "To pass file descriptors or credentials you need to send/read at
+     * least one byte" (man 7 unix) */
+    vec.iov_base = &sendchar;
+    vec.iov_len = sizeof(sendchar);
+    while((retval = sendmsg(sock_fd, &msg, 0)) == -1 && errno == EINTR);
+    if (retval != 1) {
+        perror("sending file descriptor");
+        return -1;
+    }
+    return 0;
+}
+
 static void usage()
 {
     fprintf(stderr,
@@ -420,6 +459,7 @@ int main(int argc, char *argv[])
     int numargs;
     char mypath[PATH_MAX];
     char *unmount_cmd;
+    char *commfd;
     char verstr[128];
     int flags = 0;
 
@@ -482,7 +522,9 @@ int main(int argc, char *argv[])
         return 0;
     }
 
-    if(a == argc) {
+    commfd = getenv(FUSE_COMMFD_ENV);
+
+    if(a == argc && commfd == NULL) {
         fprintf(stderr, "%s: Missing program argument\n", progname);
         exit(1);
     }
@@ -494,6 +536,14 @@ int main(int argc, char *argv[])
     if(fd == -1)
         exit(1);
 
+    if(commfd != NULL) {
+        int cfd = atoi(commfd);
+        res = send_fd(cfd, fd);
+        if(res == -1)
+            exit(1);
+        exit(0);
+    }
+
     /* Dup the file descriptor to stdin */
     if(fd != 0) {
         dup2(fd, 0);