From 0bef21e8543dda7f02b5f4cb3008a7292d249842 Mon Sep 17 00:00:00 2001
From: Nikolaus Rath <Nikolaus@rath.org>
Date: Fri, 7 Oct 2016 20:57:53 -0700
Subject: [PATCH] Removed -o nonempty option

This brings the default behavior in-line with that of the
regular `mount` command.
---
 ChangeLog.rst     | 10 ++++++++++
 lib/mount.c       | 11 -----------
 lib/mount_bsd.c   |  1 -
 lib/mount_util.c  | 33 ---------------------------------
 lib/mount_util.h  |  2 --
 util/fusermount.c | 14 +++-----------
 6 files changed, 13 insertions(+), 58 deletions(-)

diff --git a/ChangeLog.rst b/ChangeLog.rst
index 99e548a..e3ebb89 100644
--- a/ChangeLog.rst
+++ b/ChangeLog.rst
@@ -4,6 +4,15 @@ Unreleased Changes
 * The ``-o large_read`` mount option has been dropped. Hopefully no
   one uses a Linux 2.4 kernel anymore.
 
+* The `-o nonempty` mount point has been removed, mounting over
+  non-empty directories is now always allowed. This brings the
+  behavior of FUSE file systems in-line with the behavior of the
+  regular `mount` command.
+
+  File systems that do not want to allow mounting to non-empty
+  directories should perform this check themselves before handing
+  control to libfuse.
+
 * The chmod, chown, truncate, utimens and getattr handlers of the
   high-level API now all receive an additional struct fuse_file_info
   pointer. This pointer is NULL if the file is not currently open.
@@ -63,6 +72,7 @@ Unreleased Changes
   always active. File systems that want to limit the size of write
   requests should use the ``-o max_write=<N>`` option instead.
 
+
 FUSE 3.0.0pre0 (2016-10-03)
 ============================
 
diff --git a/lib/mount.c b/lib/mount.c
index 45ac60a..faac1ea 100644
--- a/lib/mount.c
+++ b/lib/mount.c
@@ -65,7 +65,6 @@ struct mount_opts {
 	int allow_other;
 	int allow_root;
 	int flags;
-	int nonempty;
 	int auto_unmount;
 	int blkdev;
 	char *fsname;
@@ -81,14 +80,12 @@ struct mount_opts {
 static const struct fuse_opt fuse_mount_opts[] = {
 	FUSE_MOUNT_OPT("allow_other",		allow_other),
 	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),
@@ -125,7 +122,6 @@ void fuse_mount_help(void)
 "    -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"
 "    -o subtype=NAME        set filesystem type\n"
@@ -421,13 +417,6 @@ static int fuse_mount_sys(const char *mnt, struct mount_opts *mo,
 		return -1;
 	}
 
-	if (!mo->nonempty) {
-		res = fuse_mnt_check_empty("fuse", mnt, stbuf.st_mode,
-					   stbuf.st_size);
-		if (res == -1)
-			return -1;
-	}
-
 	if (mo->auto_unmount) {
 		/* Tell the caller to fallback to fusermount because
 		   auto-unmount does not work otherwise. */
diff --git a/lib/mount_bsd.c b/lib/mount_bsd.c
index c838fcf..dc05506 100644
--- a/lib/mount_bsd.c
+++ b/lib/mount_bsd.c
@@ -90,7 +90,6 @@ static const struct fuse_opt fuse_mount_opts[] = {
 	 * handle them
 	 */
 	FUSE_OPT_KEY("fsname=",			KEY_KERN),
-	FUSE_OPT_KEY("nonempty",		KEY_KERN),
 	FUSE_OPT_END
 };
 
diff --git a/lib/mount_util.c b/lib/mount_util.c
index a23ab0b..8b64ca2 100644
--- a/lib/mount_util.c
+++ b/lib/mount_util.c
@@ -333,39 +333,6 @@ char *fuse_mnt_resolve_path(const char *progname, const char *orig)
 	return dst;
 }
 
-int fuse_mnt_check_empty(const char *progname, const char *mnt,
-			 mode_t rootmode, off_t rootsize)
-{
-	int isempty = 1;
-
-	if (S_ISDIR(rootmode)) {
-		struct dirent *ent;
-		DIR *dp = opendir(mnt);
-		if (dp == NULL) {
-			fprintf(stderr,
-				"%s: failed to open mountpoint for reading: %s\n",
-				progname, strerror(errno));
-			return -1;
-		}
-		while ((ent = readdir(dp)) != NULL) {
-			if (strcmp(ent->d_name, ".") != 0 &&
-			    strcmp(ent->d_name, "..") != 0) {
-				isempty = 0;
-				break;
-			}
-		}
-		closedir(dp);
-	} else if (rootsize)
-		isempty = 0;
-
-	if (!isempty) {
-		fprintf(stderr, "%s: mountpoint is not empty\n", progname);
-		fprintf(stderr, "%s: if you are sure this is safe, use the 'nonempty' mount option\n", progname);
-		return -1;
-	}
-	return 0;
-}
-
 int fuse_mnt_check_fuseblk(void)
 {
 	char buf[256];
diff --git a/lib/mount_util.h b/lib/mount_util.h
index dc5c916..55c6c5e 100644
--- a/lib/mount_util.h
+++ b/lib/mount_util.h
@@ -14,6 +14,4 @@ int fuse_mnt_remove_mount(const char *progname, const char *mnt);
 int fuse_mnt_umount(const char *progname, const char *abs_mnt,
 		    const char *rel_mnt, int lazy);
 char *fuse_mnt_resolve_path(const char *progname, const char *orig);
-int fuse_mnt_check_empty(const char *progname, const char *mnt,
-			 mode_t rootmode, off_t rootsize);
 int fuse_mnt_check_fuseblk(void);
diff --git a/util/fusermount.c b/util/fusermount.c
index b226fbd..8ba4ebf 100644
--- a/util/fusermount.c
+++ b/util/fusermount.c
@@ -714,7 +714,7 @@ static int get_string_opt(const char *s, unsigned len, const char *opt,
 
 static int do_mount(const char *mnt, char **typep, mode_t rootmode,
 		    int fd, const char *opts, const char *dev, char **sourcep,
-		    char **mnt_optsp, off_t rootsize)
+		    char **mnt_optsp)
 {
 	int res;
 	int flags = MS_NOSUID | MS_NODEV;
@@ -726,7 +726,6 @@ static int do_mount(const char *mnt, char **typep, mode_t rootmode,
 	char *subtype = NULL;
 	char *source = NULL;
 	char *type = NULL;
-	int check_empty = 1;
 	int blkdev = 0;
 
 	optbuf = (char *) malloc(strlen(opts) + 128);
@@ -759,8 +758,6 @@ static int do_mount(const char *mnt, char **typep, mode_t rootmode,
 				goto err;
 			}
 			blkdev = 1;
-		} else if (opt_eq(s, len, "nonempty")) {
-			check_empty = 0;
 		} else if (opt_eq(s, len, "auto_unmount")) {
 			auto_unmount = 1;
 		} else if (!begins_with(s, "fd=") &&
@@ -813,10 +810,6 @@ static int do_mount(const char *mnt, char **typep, mode_t rootmode,
 	sprintf(d, "fd=%i,rootmode=%o,user_id=%u,group_id=%u",
 		fd, rootmode, getuid(), getgid());
 
-	if (check_empty &&
-	    fuse_mnt_check_empty(progname, mnt, rootmode, rootsize) == -1)
-		goto err;
-
 	source = malloc((fsname ? strlen(fsname) : 0) +
 			(subtype ? strlen(subtype) : 0) + strlen(dev) + 32);
 
@@ -1082,8 +1075,7 @@ static int mount_fuse(const char *mnt, const char *opts)
 		restore_privs();
 		if (res != -1)
 			res = do_mount(real_mnt, &type, stbuf.st_mode & S_IFMT,
-				       fd, opts, dev, &source, &mnt_opts,
-				       stbuf.st_size);
+				       fd, opts, dev, &source, &mnt_opts);
 	} else
 		restore_privs();
 
@@ -1292,7 +1284,7 @@ int main(int argc, char *argv[])
 		return 0;
 
 	/* Become a daemon and wait for the parent to exit or die.
-	   ie For the control socket to get closed. 
+	   ie For the control socket to get closed.
 	   btw We don't want to use daemon() function here because
 	   it forks and messes with the file descriptors. */
 	setsid();
-- 
2.30.2