[patch] Re: getfsent(3) and spaces in fstab

Simon Barner barner at in.tum.de
Fri Aug 1 08:31:46 PDT 2003


Hi,

> For all the 'good rules' of orthonogolity and consistency etc 
> it is a good thing, however I still feel that at the level of
> the fstab where you are mounting entire file system trees, 
> the simplest naming formats are probably the best. 
> A philosophical point only, but it would keep the fstab format
> minimalistic and clean.
> 
> This point of view could probably be stated in the man page once
> the '\ ' form is implemented, as a suggested practice.

Yes, you are definitely right with this point, and I aggree that such a
hint should be added to the fstab(5) man page.

But as somebody else pointed out, one of FreeBSD's advantages is its
interoperability with other systems, and this was one of the reasons why
I decided to extent 'getfsent'.

The attached patch will allow blanks and tabs for file systems and
path names, as long as the are protected by a '\'.

For the old fstab style, blanks and tabs are not allowed as delimiters
(as it was in the old implementation).

Thus

/foo\ bar:/mnt\ point:ufs

is a valid old-style fstab entry, while

 /foo\ bar:/mnt\ point:ufs
/foo\ bar :/mnt\ point:ufs

etc. are not.

For the current fstab style, unescaped blanks and tabs are handled as
delimiters.

Simon
-------------- next part --------------
--- fstab.c.orig	Fri Aug  1 17:18:00 2003
+++ fstab.c	Fri Aug  1 17:17:46 2003
@@ -84,6 +84,78 @@
 	_fs_fstab.fs_spec = buf;
 }
 
+/*
+ * Get next token from string *stringp, where tokens are possibly-empty
+ * strings separated by characters from delim.
+ *
+ * Writes NULs into the string at *stringp to end tokens.
+ * delim need not remain constant from call to call.
+ * On return, *stringp points past the last NUL written (if there might
+ * be further tokens), or is NULL (if there are definitely no more tokens).
+ *
+ * If *stringp is NULL, es_strsep returns NULL.
+ *
+ * In contrast to strsep(3), es_strsep will allow escaped delimiters
+ * within a token.
+ */
+char *
+es_strsep(char **stringp, const char *delim)
+{
+	char	*s, *t;
+	size_t	n;
+
+	if (*stringp == '\0')	/* empty string */
+		return NULL;
+	s = *stringp;
+	s += strspn (s, delim);	/* skip delimiters */
+
+	if (*s == '\0')		/* string consists only of delimiters */
+		return NULL;
+	
+	/* skip a string consisting of non-delimiters or escapted delimiters */
+	t = s;
+	for (;;) {
+		/* skip non-delimiters */
+		n = strcspn (t, delim);
+		if (n == 0)		/* delimiters found -> end of token */
+			break;
+		t += n;
+		if (*t == '\0')		/* end of string reached */
+			break;
+
+		/* skip escaped delimiters */
+		if (*(t-1) == '\\')	/* n != 0 => *(t-1) is valid */
+			++t;
+		if (*t == '\0')		/* end of string reached */
+			break;
+	}
+
+	if (*t != '\0') {
+		*t = '\0';		/* end current token */
+		*stringp = t+1;		/* *t != '\0' => *(t+1) is valid */
+	} else
+		*stringp = 0;		/* end of string reached */	
+	
+	return s;			/* return current token */
+}
+
+/*
+ * This function removes all '\' characters from a string.
+ *
+ * It will NOT handle escape sequences as '\t' or '\n'!
+ */
+void
+remove_escapes (char **s) {
+	char *p = *s, *q;
+	while ((p = strchr (p, '\\')) != 0) {
+	    q = p;
+	    while (q[0] != '\0') {
+	        q[0] = q[1];
+		++q;
+	    }
+	}
+}
+
 static int
 fstabscan()
 {
@@ -101,9 +173,17 @@
 		++LineNo;
 		if (*line == '#' || *line == '\n')
 			continue;
-		if (!strpbrk(p, " \t")) {
+
+		/* escapted white-spaces only are allowed in old-style format */
+		cp = p;
+		while ((cp = strpbrk(cp, " \t")) != 0 &&
+			cp != p && cp[-1] == '\\')
+			++cp;
+		if (cp == 0) {
 			_fs_fstab.fs_spec = strsep(&p, ":\n");
+			remove_escapes (&_fs_fstab.fs_spec);
 			_fs_fstab.fs_file = strsep(&p, ":\n");
+			remove_escapes (&_fs_fstab.fs_file);
 			fixfsfile();
 			_fs_fstab.fs_type = strsep(&p, ":\n");
 			if (_fs_fstab.fs_type) {
@@ -124,14 +204,18 @@
 			goto bad;
 		}
 /* OLD_STYLE_FSTAB */
-		while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0')
+		while ((cp = es_strsep(&p, " \t\n")) != NULL && *cp == '\0')
 			;
 		_fs_fstab.fs_spec = cp;
+		remove_escapes (&_fs_fstab.fs_spec);
 		if (!_fs_fstab.fs_spec || *_fs_fstab.fs_spec == '#')
 			continue;
-		while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0')
+		while ((cp = es_strsep(&p, " \t\n")) != NULL && *cp == '\0')
 			;
+		if (cp == 0)
+			goto bad;
 		_fs_fstab.fs_file = cp;
+		remove_escapes (&_fs_fstab.fs_file);
 		fixfsfile();
 		while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0')
 			;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 187 bytes
Desc: Digital signature
Url : http://lists.freebsd.org/pipermail/freebsd-hackers/attachments/20030801/60e39dbb/attachment.bin


More information about the freebsd-hackers mailing list