From d6e9f88da7cea46cf63d30911b9297ccf1befd5c Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Fri, 25 Oct 2002 11:40:14 +0000 Subject: [PATCH] use fuse_mount in fuse_main --- ChangeLog | 5 ++ include/fuse.h | 5 +- lib/helper.c | 152 ++++++++++++++++++++++++-------------------- makeconf.sh | 6 ++ util/Makefile.am | 3 +- util/fuse_ioslave.c | 61 ------------------ util/fusermount.c | 52 ++++++++++++++- 7 files changed, 148 insertions(+), 136 deletions(-) delete mode 100644 util/fuse_ioslave.c diff --git a/ChangeLog b/ChangeLog index 8c01735..e9a14af 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2002-10-25 Miklos Szeredi + + * Use Mark Glines' fd passing method for default operation instead + of old reexec + 2002-10-22 Miklos Szeredi * fix "Stale NFS file handle" bug caused by changes in 2.4.19 diff --git a/include/fuse.h b/include/fuse.h index 78cd877..6a3ed3a 100644 --- a/include/fuse.h +++ b/include/fuse.h @@ -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. diff --git a/lib/helper.c b/lib/helper.c index f523f99..559e992 100644 --- a/lib/helper.c +++ b/lib/helper.c @@ -20,8 +20,11 @@ #include #include -#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); diff --git a/makeconf.sh b/makeconf.sh index 2c97050..8cd29ad 100755 --- a/makeconf.sh +++ b/makeconf.sh @@ -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'." diff --git a/util/Makefile.am b/util/Makefile.am index 0e4434f..48f9957 100644 --- a/util/Makefile.am +++ b/util/Makefile.am @@ -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 index df7c66d..0000000 --- a/util/fuse_ioslave.c +++ /dev/null @@ -1,61 +0,0 @@ -#include /* fprintf */ -#include /* errno */ -#include /* strerror */ -#include /* read,write,close */ -#include /* getenv,strtol */ -#include /* select */ -#include /* send, recv */ -#include /* 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; -} diff --git a/util/fusermount.c b/util/fusermount.c index b3f46cf..ac464d2 100644 --- a/util/fusermount.c +++ b/util/fusermount.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #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); -- 2.30.2