summaryrefslogtreecommitdiffstats
path: root/fuse/mount.c
diff options
context:
space:
mode:
Diffstat (limited to 'fuse/mount.c')
-rw-r--r--fuse/mount.c66
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: