Add write buffer for tar writes

update fuse to 2.9.2

catch return from unlink so that we don't print error messages when things work
Change-Id: I1115039a0fa5d9d73f78ef1abd79755d7ffd9d96
diff --git a/fuse/mount.c b/fuse/mount.c
index 88ab597..af7218f 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 @@
 	int ishelp;
 	int flags;
 	int nonempty;
+	int auto_unmount;
 	int blkdev;
 	char *fsname;
 	char *subtype;
@@ -70,11 +86,13 @@
 	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 @@
 	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 @@
 }
 
 #define FUSERMOUNT_DIR "/usr/bin"
-
 static void exec_fusermount(const char *argv[])
 {
 	execv(FUSERMOUNT_DIR "/" FUSERMOUNT_PROG, (char **) argv);
@@ -144,7 +162,7 @@
 	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 @@
 	{"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 @@
 	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 @@
 	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 @@
 
 		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 @@
 
 	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 @@
 			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 @@
 		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 @@
 		if (res == -1)
 			goto out_umount;
 	}
+#endif /* IGNORE_MTAB */
+#endif /* __NetBSD__ */
 	free(type);
 	free(source);
 
@@ -572,13 +614,13 @@
 				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: