Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 4 Aug 2003 02:33:31 +0200
From:      Simon Barner <barner@in.tum.de>
To:        Terry Lambert <tlambert2@mindspring.com>
Cc:        kientzle@acm.org
Subject:   Re: [patch] Re: getfsent(3) and spaces in fstab
Message-ID:  <20030804003331.GA408@zi025.glhnet.mhn.de>
In-Reply-To: <3F2B75E2.FBC18052@mindspring.com>
References:  <20030730224505.GD531@zi025.glhnet.mhn.de> <1059607242.64020.5.camel@mjtdev1.dand06.au.bytecraft.au.com> <3F285560.2090607@acm.org> <1059608748.64020.10.camel@mjtdev1.dand06.au.bytecraft.au.com> <002201c356fa$4a66a700$1200a8c0@gsicomp.on.ca> <20030731134343.GB1323@zi025.glhnet.mhn.de> <1059693358.64020.31.camel@mjtdev1.dand06.au.bytecraft.au.com> <20030801153142.GA487@zi025.glhnet.mhn.de> <3F2B75E2.FBC18052@mindspring.com>

next in thread | previous in thread | raw e-mail | index | archive | help

--cmJC7u66zC7hs+87
Content-Type: multipart/mixed; boundary="HlL+5n6rz5pIUxbD"
Content-Disposition: inline


--HlL+5n6rz5pIUxbD
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi Terry,

> You need to add '\\' to the list of characters that can be escaped,
> or you've just traded the inability to specify '\t' or ' ' for an
> inability to speciy '\\'.

Oh yes, I have overlook this special case. I revised my patch in order
to get this right.

Simon

--HlL+5n6rz5pIUxbD
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="patch-fstab.c"
Content-Transfer-Encoding: quoted-printable

--- fstab.c.orig	Fri Aug  1 17:18:00 2003
+++ fstab.c	Mon Aug  4 01:46:55 2003
@@ -49,6 +49,7 @@
 #include <errno.h>
 #include <fstab.h>
 #include <paths.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -84,6 +85,140 @@
 	_fs_fstab.fs_spec =3D buf;
 }
=20
+/*
+ * 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. These escaped characters as well as the special case
+ * '\\' will be converted appropriately ('\<delim>' -> '<delim>, '\\' -> '=
\'
+ *
+ */
+char *
+es_strsep(char **stringp, const char *delim)
+{
+	bool	escaped=3Dfalse;
+	char	*s, *t, *u;
+	int	i;
+
+
+	if (*stringp =3D=3D '\0')	/* empty string */
+		return NULL;
+	s =3D *stringp;
+	s +=3D strspn (s, delim);	/* skip delimiters */
+
+	if (*s =3D=3D '\0')		/* string consists only of delimiters */
+		return NULL;
+=09
+	/*
+	 * skip a string consisting of non-delimiters,
+	 * escapted delimiters or '\\'
+	*/
+	for (t =3D s; *t !=3D '\0'; ++t) {
+		if (*t =3D=3D '\\') {
+		    if (escaped) {	/* convert \\ to \ */
+			--t;
+		        u =3D t;
+		        escaped =3D false;
+		        while (u[0] !=3D '\0') {
+		            u[0] =3D u[1];
+		            ++u;
+		        }
+		    } else		/* start \-Sequence */
+			escaped =3D true;
+		    continue;
+		}
+	=09
+		/* search for delimiter */
+		for (i=3D0; delim[i] !=3D '\0'; ++i) {
+		    if (*t =3D=3D delim[i])
+		        break;
+		}
+	=09
+		/* un-escaped delimiter found =3D> end of token */
+		if (!escaped && delim[i] !=3D '\0')
+		    break;
+		   =20
+		/* escaped delimiter found =3D> remove / */
+		if (escaped) {
+    		    --t;
+	            u =3D t;
+                    escaped =3D false;
+		    while (u[0] !=3D '\0') {
+		        u[0] =3D u[1];
+		        ++u;
+		    }
+		}
+	}
+
+	if (*t !=3D '\0') {
+		*t =3D '\0';		/* end current token */
+		*stringp =3D t+1;		/* *t !=3D '\0' =3D> *(t+1) is valid */
+	} else
+		*stringp =3D 0;		/* end of string reached */=09
+=09
+	return s;			/* return current token */
+}
+
+/*
+ * This function converts escaped characters:
+ * '\<delim>' -> '<delim>', '\\' -> '\'
+ *=20
+ * If there are unescaped delimiters, 'false' will be return to indicate
+ * an error, otherwise remove_escape returns 'true'.
+ */
+bool remove_escapes (char **s, const char* delim) {
+	bool	escaped=3Dfalse;
+	char	*t, *u;
+	int	i;
+=09
+	for (t =3D *s; *t !=3D '\0'; ++t) {
+		if (*t =3D=3D '\\') {
+		    if (escaped) {	/* convert \\ to \ */
+			--t;
+		        u =3D t;
+		        escaped =3D false;
+		        while (u[0] !=3D '\0') {
+		            u[0] =3D u[1];
+		            ++u;
+		        }
+		    } else		/* start \-Sequence */
+			escaped =3D true;
+		    continue;
+		}
+	=09
+		/* search for delimiter */
+		for (i=3D0; delim[i] !=3D '\0'; ++i) {
+		    if (*t =3D=3D delim[i])
+		        break;
+		}
+	=09
+		/* un-escaped delimiter found =3D> error */
+		if (!escaped && delim[i] !=3D '\0')
+			return false;
+
+		/* escaped delimiter found =3D> remove / */
+		if (escaped) {
+    		    --t;
+	            u =3D t;
+                    escaped =3D false;
+		    while (u[0] !=3D '\0') {
+		        u[0] =3D u[1];
+		        ++u;
+		    }
+		}
+	}
+=09
+	return true;
+}
+
 static int
 fstabscan()
 {
@@ -101,9 +236,19 @@
 		++LineNo;
 		if (*line =3D=3D '#' || *line =3D=3D '\n')
 			continue;
-		if (!strpbrk(p, " \t")) {
+
+		/* escapted white-spaces only are allowed in old-style format */
+		cp =3D p;
+		while ((cp =3D strpbrk(cp, " \t")) !=3D 0 &&
+			cp !=3D p && cp[-1] =3D=3D '\\')
+			++cp;
+		if (cp =3D=3D 0) {
 			_fs_fstab.fs_spec =3D strsep(&p, ":\n");
+			if (!remove_escapes (&_fs_fstab.fs_spec, " \t"))
+			    goto bad;
 			_fs_fstab.fs_file =3D strsep(&p, ":\n");
+			if (!remove_escapes (&_fs_fstab.fs_file, " \t"))
+			    goto bad;
 			fixfsfile();
 			_fs_fstab.fs_type =3D strsep(&p, ":\n");
 			if (_fs_fstab.fs_type) {
@@ -124,13 +269,15 @@
 			goto bad;
 		}
 /* OLD_STYLE_FSTAB */
-		while ((cp =3D strsep(&p, " \t\n")) !=3D NULL && *cp =3D=3D '\0')
+		while ((cp =3D es_strsep(&p, " \t\n")) !=3D NULL && *cp =3D=3D '\0')
 			;
 		_fs_fstab.fs_spec =3D cp;
 		if (!_fs_fstab.fs_spec || *_fs_fstab.fs_spec =3D=3D '#')
 			continue;
-		while ((cp =3D strsep(&p, " \t\n")) !=3D NULL && *cp =3D=3D '\0')
+		while ((cp =3D es_strsep(&p, " \t\n")) !=3D NULL && *cp =3D=3D '\0')
 			;
+		if (cp =3D=3D 0)
+			goto bad;
 		_fs_fstab.fs_file =3D cp;
 		fixfsfile();
 		while ((cp =3D strsep(&p, " \t\n")) !=3D NULL && *cp =3D=3D '\0')

--HlL+5n6rz5pIUxbD--

--cmJC7u66zC7hs+87
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: Digital signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.2 (FreeBSD)

iD8DBQE/LanbCkn+/eutqCoRAs7XAKCpZ+27mnva6IneR3gtL1BpkjqV/ACg4oed
jyXs4Off13grX1MU/tpNx7A=
=/Mku
-----END PGP SIGNATURE-----

--cmJC7u66zC7hs+87--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030804003331.GA408>