diff options
Diffstat (limited to '')
-rw-r--r-- | fuse/mount.c | 66 |
1 files changed, 54 insertions, 12 deletions
diff --git a/fuse/mount.c b/fuse/mount.c index 88ab59721..af7218fa4 100644 --- a/fuse/mount.c +++ b/fuse/mount.c @@ -17,6 +17,7 @@ #include <stdlib.h> #include <unistd.h> #include <stddef.h> +#include <string.h> #include <fcntl.h> #include <errno.h> #include <sys/poll.h> @@ -25,6 +26,20 @@ #include <sys/wait.h> #include <sys/mount.h> +#ifdef __NetBSD__ +#include <perfuse.h> + +#define MS_RDONLY MNT_RDONLY +#define MS_NOSUID MNT_NOSUID +#define MS_NODEV MNT_NODEV +#define MS_NOEXEC MNT_NOEXEC +#define MS_SYNCHRONOUS MNT_SYNCHRONOUS +#define MS_NOATIME MNT_NOATIME + + +#define umount2(mnt, flags) unmount(mnt, (flags == 2) ? MNT_FORCE : 0) +#endif + #define FUSERMOUNT_PROG "fusermount" #define FUSE_COMMFD_ENV "_FUSE_COMMFD" @@ -54,6 +69,7 @@ struct mount_opts { int ishelp; int flags; int nonempty; + int auto_unmount; int blkdev; char *fsname; char *subtype; @@ -70,11 +86,13 @@ static const struct fuse_opt fuse_mount_opts[] = { FUSE_MOUNT_OPT("allow_root", allow_root), FUSE_MOUNT_OPT("nonempty", nonempty), FUSE_MOUNT_OPT("blkdev", blkdev), + FUSE_MOUNT_OPT("auto_unmount", auto_unmount), FUSE_MOUNT_OPT("fsname=%s", fsname), FUSE_MOUNT_OPT("subtype=%s", subtype), FUSE_OPT_KEY("allow_other", KEY_KERN_OPT), FUSE_OPT_KEY("allow_root", KEY_ALLOW_ROOT), FUSE_OPT_KEY("nonempty", KEY_FUSERMOUNT_OPT), + FUSE_OPT_KEY("auto_unmount", KEY_FUSERMOUNT_OPT), FUSE_OPT_KEY("blkdev", KEY_FUSERMOUNT_OPT), FUSE_OPT_KEY("fsname=", KEY_FUSERMOUNT_OPT), FUSE_OPT_KEY("subtype=", KEY_SUBTYPE_OPT), @@ -110,6 +128,7 @@ static void mount_help(void) fprintf(stderr, " -o allow_other allow access to other users\n" " -o allow_root allow access to root\n" +" -o auto_unmount auto unmount on process termination\n" " -o nonempty allow mounts over non-empty file/dir\n" " -o default_permissions enable permission checking by kernel\n" " -o fsname=NAME set filesystem name\n" @@ -120,7 +139,6 @@ static void mount_help(void) } #define FUSERMOUNT_DIR "/usr/bin" - static void exec_fusermount(const char *argv[]) { execv(FUSERMOUNT_DIR "/" FUSERMOUNT_PROG, (char **) argv); @@ -144,7 +162,7 @@ struct mount_flags { int on; }; -static struct mount_flags mount_flags[] = { +static const struct mount_flags mount_flags[] = { {"rw", MS_RDONLY, 0}, {"ro", MS_RDONLY, 1}, {"suid", MS_NOSUID, 0}, @@ -157,7 +175,9 @@ static struct mount_flags mount_flags[] = { {"sync", MS_SYNCHRONOUS, 1}, {"atime", MS_NOATIME, 0}, {"noatime", MS_NOATIME, 1}, +#ifndef __NetBSD__ {"dirsync", MS_DIRSYNC, 1}, +#endif {NULL, 0, 0} }; @@ -239,6 +259,7 @@ static int receive_fd(int fd) iov.iov_base = buf; iov.iov_len = 1; + memset(&msg, 0, sizeof(msg)); msg.msg_name = 0; msg.msg_namelen = 0; msg.msg_iov = &iov; @@ -319,8 +340,8 @@ void fuse_unmount_compat22(const char *mountpoint) fuse_kern_unmount(mountpoint, -1); } -static int fuse_mount_fusermount(const char *mountpoint, const char *opts, - int quiet) +static int fuse_mount_fusermount(const char *mountpoint, struct mount_opts *mo, + const char *opts, int quiet) { int fds[2], pid; int res; @@ -352,8 +373,10 @@ static int fuse_mount_fusermount(const char *mountpoint, const char *opts, if (quiet) { int fd = open("/dev/null", O_RDONLY); - dup2(fd, 1); - dup2(fd, 2); + if (fd != -1) { + dup2(fd, 1); + dup2(fd, 2); + } } argv[a++] = FUSERMOUNT_PROG; @@ -376,15 +399,24 @@ static int fuse_mount_fusermount(const char *mountpoint, const char *opts, close(fds[0]); rv = receive_fd(fds[1]); - close(fds[1]); - waitpid(pid, NULL, 0); /* bury zombie */ + + if (!mo->auto_unmount) { + /* with auto_unmount option fusermount will not exit until + this socket is closed */ + close(fds[1]); + waitpid(pid, NULL, 0); /* bury zombie */ + } return rv; } int fuse_mount_compat22(const char *mountpoint, const char *opts) { - return fuse_mount_fusermount(mountpoint, opts, 0); + struct mount_opts mo; + memset(&mo, 0, sizeof(mo)); + mo.flags = MS_NOSUID | MS_NODEV; + + return fuse_mount_fusermount(mountpoint, &mo, opts, 0); } static int fuse_mount_sys(const char *mnt, struct mount_opts *mo, @@ -417,6 +449,12 @@ static int fuse_mount_sys(const char *mnt, struct mount_opts *mo, return -1; } + if (mo->auto_unmount) { + /* Tell the caller to fallback to fusermount because + auto-unmount does not work otherwise. */ + return -2; + } + fd = open(devname, O_RDWR); if (fd == -1) { if (errno == ENODEV || errno == ENOENT) @@ -486,6 +524,8 @@ static int fuse_mount_sys(const char *mnt, struct mount_opts *mo, goto out_close; } +#ifndef __NetBSD__ +#ifndef IGNORE_MTAB if (geteuid() == 0) { char *newmnt = fuse_mnt_resolve_path("fuse", mnt); res = -1; @@ -498,6 +538,8 @@ static int fuse_mount_sys(const char *mnt, struct mount_opts *mo, if (res == -1) goto out_umount; } +#endif /* IGNORE_MTAB */ +#endif /* __NetBSD__ */ free(type); free(source); @@ -572,13 +614,13 @@ int fuse_kern_mount(const char *mountpoint, struct fuse_args *args) goto out; } - res = fuse_mount_fusermount(mountpoint, tmp_opts, 1); + res = fuse_mount_fusermount(mountpoint, &mo, tmp_opts, 1); free(tmp_opts); if (res == -1) - res = fuse_mount_fusermount(mountpoint, + res = fuse_mount_fusermount(mountpoint, &mo, mnt_opts, 0); } else { - res = fuse_mount_fusermount(mountpoint, mnt_opts, 0); + res = fuse_mount_fusermount(mountpoint, &mo, mnt_opts, 0); } } out: |