mirror of
https://github.com/libfuse/libfuse.git
synced 2024-11-23 12:14:15 +08:00
use fuse_mount in fuse_main
This commit is contained in:
parent
5e5d61fea4
commit
d6e9f88da7
@ -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>
|
2002-10-22 Miklos Szeredi <mszeredi@inf.bme.hu>
|
||||||
|
|
||||||
* fix "Stale NFS file handle" bug caused by changes in 2.4.19
|
* fix "Stale NFS file handle" bug caused by changes in 2.4.19
|
||||||
|
@ -116,10 +116,11 @@ extern "C" {
|
|||||||
* fuse_new()
|
* fuse_new()
|
||||||
*
|
*
|
||||||
* @param mountpoint the mount point path
|
* @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
|
* @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.
|
* Create a new FUSE filesystem.
|
||||||
|
152
lib/helper.c
152
lib/helper.c
@ -20,8 +20,11 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
||||||
#define FUSE_MOUNTED_ENV "_FUSE_MOUNTED"
|
#define FUSE_MOUNTED_ENV "_FUSE_MOUNTED"
|
||||||
#define FUSE_UMOUNT_CMD_ENV "_FUSE_UNMOUNT_CMD"
|
#define FUSE_UMOUNT_CMD_ENV "_FUSE_UNMOUNT_CMD"
|
||||||
|
#define FUSE_COMMFD_ENV "_FUSE_COMMFD"
|
||||||
|
|
||||||
|
#define FUSERMOUNT_PROG "fusermount"
|
||||||
|
|
||||||
static void usage(char *progname)
|
static void usage(char *progname)
|
||||||
{
|
{
|
||||||
@ -35,51 +38,22 @@ static void usage(char *progname)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char umount_cmd[1024];
|
||||||
|
static int fuse_fd;
|
||||||
|
|
||||||
static void fuse_unmount()
|
static void fuse_unmount()
|
||||||
{
|
{
|
||||||
close(0);
|
close(fuse_fd);
|
||||||
system(getenv(FUSE_UMOUNT_CMD_ENV));
|
if(umount_cmd[0] != '\0')
|
||||||
}
|
system(umount_cmd);
|
||||||
|
|
||||||
static int fuse_mount_obsolete(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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return value:
|
/* return value:
|
||||||
* >= 0 => fd
|
* >= 0 => fd
|
||||||
* -1 => error
|
* -1 => error
|
||||||
*/
|
*/
|
||||||
int receive_fd(int fd) {
|
static int receive_fd(int fd)
|
||||||
|
{
|
||||||
struct msghdr msg;
|
struct msghdr msg;
|
||||||
struct iovec iov;
|
struct iovec iov;
|
||||||
char buf[1];
|
char buf[1];
|
||||||
@ -120,46 +94,63 @@ int receive_fd(int fd) {
|
|||||||
return *(int*)CMSG_DATA(cmsg);
|
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 fds[2], pid;
|
||||||
int rv, fd;
|
int res;
|
||||||
char env[10];
|
int rv;
|
||||||
|
|
||||||
/* FIXME: parse mount_args (or just pass it to fusermount ???) */
|
|
||||||
mount_args = mount_args;
|
|
||||||
|
|
||||||
/* make sure the socket fds are greater than 0 */
|
snprintf(umount_cmd, sizeof(umount_cmd) - 1, "%s -u %s", mountprog,
|
||||||
fd = open("/dev/null",O_RDONLY);
|
mountpoint);
|
||||||
rv = socketpair(PF_UNIX,SOCK_STREAM,0,fds);
|
|
||||||
close(fd);
|
res = socketpair(PF_UNIX, SOCK_STREAM, 0, fds);
|
||||||
if(rv) {
|
if(res == -1) {
|
||||||
fprintf(stderr,"fuse: failed to socketpair()\n");
|
perror("fuse: socketpair() failed");
|
||||||
close(fd);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pid = fork();
|
pid = fork();
|
||||||
if(pid < 0) {
|
if(pid == -1) {
|
||||||
fprintf(stderr,"fuse: failed to fork()\n");
|
perror("fuse: fork() failed");
|
||||||
close(fds[0]);
|
close(fds[0]);
|
||||||
close(fds[1]);
|
close(fds[1]);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pid == 0) {
|
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]);
|
close(fds[1]);
|
||||||
fcntl(fds[0],F_SETFD,0);
|
fcntl(fds[0], F_SETFD, 0);
|
||||||
snprintf(env,sizeof(env),"%i",fds[0]);
|
snprintf(env, sizeof(env), "%i", fds[0]);
|
||||||
setenv("_FUSE_IOSLAVE_FD",env,1);
|
setenv(FUSE_COMMFD_ENV, env, 1);
|
||||||
execlp("fusermount","fusermount",mountpoint,"fuse_ioslave",NULL);
|
execvp(mountprog, newargv);
|
||||||
fprintf(stderr,"fuse: failed to exec fusermount\n");
|
perror("fuse: failed to exec fusermount");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = fds[1];
|
|
||||||
close(fds[0]);
|
close(fds[0]);
|
||||||
rv = receive_fd(fd);
|
rv = receive_fd(fds[1]);
|
||||||
close(fd);
|
close(fds[1]);
|
||||||
waitpid(pid,NULL,0); /* bury zombie */
|
waitpid(pid, NULL, 0); /* bury zombie */
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,20 +185,41 @@ static void set_signal_handlers()
|
|||||||
|
|
||||||
void fuse_main(int argc, char *argv[], const struct fuse_operations *op)
|
void fuse_main(int argc, char *argv[], const struct fuse_operations *op)
|
||||||
{
|
{
|
||||||
int fd;
|
int argctr = 1;
|
||||||
int argctr;
|
|
||||||
int flags;
|
int flags;
|
||||||
int multithreaded;
|
int multithreaded;
|
||||||
struct fuse *fuse;
|
struct fuse *fuse;
|
||||||
|
char *isreexec = getenv(FUSE_MOUNTED_ENV);
|
||||||
|
|
||||||
fd = fuse_mount_obsolete(&argc, argv);
|
if(isreexec == NULL) {
|
||||||
if(fd == -1)
|
if(argc < 2 || argv[1][0] == '-')
|
||||||
exit(1);
|
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);
|
atexit(fuse_unmount);
|
||||||
set_signal_handlers();
|
set_signal_handlers();
|
||||||
|
|
||||||
argctr = 1;
|
|
||||||
flags = 0;
|
flags = 0;
|
||||||
multithreaded = 1;
|
multithreaded = 1;
|
||||||
for(; argctr < argc && argv[argctr][0] == '-'; argctr ++) {
|
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);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
fuse = fuse_new(fd, flags, op);
|
fuse = fuse_new(fuse_fd, flags, op);
|
||||||
|
|
||||||
if(multithreaded)
|
if(multithreaded)
|
||||||
fuse_loop_mt(fuse);
|
fuse_loop_mt(fuse);
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
|
|
||||||
|
echo Running aclocal...
|
||||||
aclocal
|
aclocal
|
||||||
|
echo Running autoheader...
|
||||||
autoheader
|
autoheader
|
||||||
|
echo Running autoconf...
|
||||||
autoconf
|
autoconf
|
||||||
|
echo Running automake...
|
||||||
automake -a -c
|
automake -a -c
|
||||||
|
rm -f config.cache config.status
|
||||||
|
echo "To compile run './configure', and then 'make'."
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
## Process this file with automake to produce Makefile.in
|
## Process this file with automake to produce Makefile.in
|
||||||
|
|
||||||
bin_PROGRAMS = fusermount fuse_ioslave
|
bin_PROGRAMS = fusermount
|
||||||
|
|
||||||
fusermount_SOURCES = fusermount.c
|
fusermount_SOURCES = fusermount.c
|
||||||
fuse_ioslave_SOURCES = fuse_ioslave.c
|
|
||||||
|
|
||||||
install-exec-hook:
|
install-exec-hook:
|
||||||
-chown root $(DESTDIR)$(bindir)/fusermount
|
-chown root $(DESTDIR)$(bindir)/fusermount
|
||||||
|
@ -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;
|
|
||||||
}
|
|
@ -29,6 +29,8 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
#include <sys/fsuid.h>
|
#include <sys/fsuid.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
#include <linux/fuse.h>
|
#include <linux/fuse.h>
|
||||||
|
|
||||||
#define CHECK_PERMISSION 1
|
#define CHECK_PERMISSION 1
|
||||||
@ -42,6 +44,7 @@
|
|||||||
#define FUSE_MOUNTED_ENV "_FUSE_MOUNTED"
|
#define FUSE_MOUNTED_ENV "_FUSE_MOUNTED"
|
||||||
#define FUSE_UMOUNT_CMD_ENV "_FUSE_UNMOUNT_CMD"
|
#define FUSE_UMOUNT_CMD_ENV "_FUSE_UNMOUNT_CMD"
|
||||||
#define FUSE_KERNEL_VERSION_ENV "_FUSE_KERNEL_VERSION"
|
#define FUSE_KERNEL_VERSION_ENV "_FUSE_KERNEL_VERSION"
|
||||||
|
#define FUSE_COMMFD_ENV "_FUSE_COMMFD"
|
||||||
|
|
||||||
const char *progname;
|
const char *progname;
|
||||||
|
|
||||||
@ -395,6 +398,42 @@ static char *resolve_path(const char *orig, int unmount)
|
|||||||
return strdup(buf);
|
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()
|
static void usage()
|
||||||
{
|
{
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
@ -420,6 +459,7 @@ int main(int argc, char *argv[])
|
|||||||
int numargs;
|
int numargs;
|
||||||
char mypath[PATH_MAX];
|
char mypath[PATH_MAX];
|
||||||
char *unmount_cmd;
|
char *unmount_cmd;
|
||||||
|
char *commfd;
|
||||||
char verstr[128];
|
char verstr[128];
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
|
|
||||||
@ -482,7 +522,9 @@ int main(int argc, char *argv[])
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(a == argc) {
|
commfd = getenv(FUSE_COMMFD_ENV);
|
||||||
|
|
||||||
|
if(a == argc && commfd == NULL) {
|
||||||
fprintf(stderr, "%s: Missing program argument\n", progname);
|
fprintf(stderr, "%s: Missing program argument\n", progname);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@ -494,6 +536,14 @@ int main(int argc, char *argv[])
|
|||||||
if(fd == -1)
|
if(fd == -1)
|
||||||
exit(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 */
|
/* Dup the file descriptor to stdin */
|
||||||
if(fd != 0) {
|
if(fd != 0) {
|
||||||
dup2(fd, 0);
|
dup2(fd, 0);
|
||||||
|
Loading…
Reference in New Issue
Block a user