PATCH: mount -O list

Michael Abbott michael at araneidae.co.uk
Tue Dec 1 09:30:15 UTC 2009


The attached patch implements support for a list of filter options on the 
-O option.

I have assumed that when 
	-O a,nob,c
is requested that this should be interpreted as requiring that both -o a 
and -o c are specified, as well as that -o b is *not* specified.  
Unfortunately the mount man page is annoyingly ambiguous on this.


diff -ur busybox-1.15.2/util-linux/mount.c busybox-1.15.2-patched/util-linux/mount.c
--- busybox-1.15.2/util-linux/mount.c	2009-10-08 01:59:09.000000000 +0100
+++ busybox-1.15.2-patched/util-linux/mount.c	2009-12-01 09:19:07.000000000 +0000
@@ -1775,42 +1775,64 @@
 }
 
 /* -O support
- * Unlike -t, -O should interpret "no" prefix differently:
- * -t noa,b,c = -t no(a,b,c) = mount all except fs'es with types a,b, and c
- * -O noa,b,c = -O noa,b,c = mount all with without option a,
- * or with option b or c.
- * But for now we do not support -O a,b,c at all (only -O a).
+ *    -O interprets a list of filter options which select whether a mount
+ * point will be mounted: only mounts with options matching *all* filtering
+ * options will be selected. 
+ *    By default each -O filter option must be present in the list of mount
+ * options, but if it is prefixed by "no" then it must be absent.  For
+ * example,
+ *  -O a,nob,c  matches  -o a,c  but  fails to match  -o a,b,c
+ *              (and also fails to match  -o a  because  -o c  is absent).
  *
- * Another difference from -t support (match_fstype) is that
- * we need to examine the _list_ of options in fsopt, not just a string.
+ * It is different from -t in that each option is matched exactly; a leading
+ * no at the beginning of one option does not negate the rest.
  */
-static int match_opt(const char *fs_opt, const char *O_opt)
+static int match_opt(const char *fs_opt_in, const char *O_opt)
 {
-	int match = 1;
-	int len;
-
 	if (!O_opt)
-		return match;
-
-	if (O_opt[0] == 'n' && O_opt[1] == 'o') {
-		match--;
-		O_opt += 2;
-	}
-
-	len = strlen(O_opt);
-	while (1) {
-		if (strncmp(fs_opt, O_opt, len) == 0
-		 && (fs_opt[len] == '\0' || fs_opt[len] == ',')
-		) {
-			return match;
+		return 1;
+	while (*O_opt)
+	{
+		const char *O_comma;
+		int O_len;
+		const char *fs_opt = fs_opt_in;
+		int match = 0;
+		/* If option begins no then treat as an inverted match: matching is a
+		 * failure. */
+		if (O_opt[0] == 'n' && O_opt[1] == 'o') {
+			match = 1;
+			O_opt += 2;
 		}
-		fs_opt = strchr(fs_opt, ',');
-		if (!fs_opt)
+		/* Isolate the current O option (after processing any no prefix). */
+		O_comma = strchr(O_opt, ',');
+		O_len = O_comma ? O_comma - O_opt : strlen(O_opt);
+		/* Check for a match against existing options. */
+		while (1) {
+			if (strncmp(fs_opt, O_opt, O_len) == 0
+			 && (fs_opt[O_len] == '\0' || fs_opt[O_len] == ',')
+			) {
+				if (match)
+					return 0;	// no match selected, but option found
+				else {
+					match = 1;	// option found, so try for next O option
+					break;
+				}
+			}
+			fs_opt = strchr(fs_opt, ',');
+			if (!fs_opt)
+				break;
+			fs_opt++;
+		}
+		if (match == 0)
+			return 0;			// match wanted but not found
+		/* Step to the next O option. */
+		if (O_comma)
+			O_opt = O_comma + 1;
+		else
 			break;
-		fs_opt++;
 	}
-
-	return !match;
+	/* If we get here then everything matched. */
+	return 1;
 }
 
 // Parse options, if necessary parse fstab/mtab, and call singlemount for


More information about the busybox mailing list