summaryrefslogtreecommitdiff
path: root/lib/mount.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mount.c')
-rw-r--r--lib/mount.c73
1 files changed, 66 insertions, 7 deletions
diff --git a/lib/mount.c b/lib/mount.c
index 3990243..9c233a3 100644
--- a/lib/mount.c
+++ b/lib/mount.c
@@ -322,6 +322,65 @@ void fuse_kern_unmount(const char *mountpoint, int fd)
waitpid(pid, NULL, 0);
}
+static int setup_auto_unmount(const char *mountpoint, int quiet)
+{
+ int fds[2], pid;
+ int res;
+
+ if (!mountpoint) {
+ fuse_log(FUSE_LOG_ERR, "fuse: missing mountpoint parameter\n");
+ return -1;
+ }
+
+ res = socketpair(PF_UNIX, SOCK_STREAM, 0, fds);
+ if(res == -1) {
+ perror("fuse: socketpair() failed");
+ return -1;
+ }
+
+ pid = fork();
+ if(pid == -1) {
+ perror("fuse: fork() failed");
+ close(fds[0]);
+ close(fds[1]);
+ return -1;
+ }
+
+ if(pid == 0) {
+ char env[10];
+ const char *argv[32];
+ int a = 0;
+
+ if (quiet) {
+ int fd = open("/dev/null", O_RDONLY);
+ if (fd != -1) {
+ dup2(fd, 1);
+ dup2(fd, 2);
+ }
+ }
+
+ argv[a++] = FUSERMOUNT_PROG;
+ argv[a++] = "--auto-unmount";
+ argv[a++] = "--";
+ argv[a++] = mountpoint;
+ argv[a++] = NULL;
+
+ close(fds[1]);
+ fcntl(fds[0], F_SETFD, 0);
+ snprintf(env, sizeof(env), "%i", fds[0]);
+ setenv(FUSE_COMMFD_ENV, env, 1);
+ exec_fusermount(argv);
+ perror("fuse: failed to exec fusermount3");
+ _exit(1);
+ }
+
+ close(fds[0]);
+
+ // Now fusermount3 will only exit when fds[1] closes automatically when our
+ // process exits.
+ return 0;
+}
+
static int fuse_mount_fusermount(const char *mountpoint, struct mount_opts *mo,
const char *opts, int quiet)
{
@@ -422,12 +481,6 @@ static int fuse_mount_sys(const char *mnt, struct mount_opts *mo,
return -1;
}
- if (mo->auto_unmount) {
- /* Tell the caller to fallback to fusermount3 because
- auto-unmount does not work otherwise. */
- return -2;
- }
-
fd = open(devname, O_RDWR | O_CLOEXEC);
if (fd == -1) {
if (errno == ENODEV || errno == ENOENT)
@@ -590,7 +643,13 @@ int fuse_kern_mount(const char *mountpoint, struct mount_opts *mo)
goto out;
res = fuse_mount_sys(mountpoint, mo, mnt_opts);
- if (res == -2) {
+ if (res >= 0 && mo->auto_unmount) {
+ if(0 > setup_auto_unmount(mountpoint, 0)) {
+ // Something went wrong, let's umount like in fuse_mount_sys.
+ umount2(mountpoint, MNT_DETACH); /* lazy umount */
+ res = -1;
+ }
+ } else if (res == -2) {
if (mo->fusermount_opts &&
fuse_opt_add_opt(&mnt_opts, mo->fusermount_opts) == -1)
goto out;