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
--- 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 = 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. 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=false;
+       char    *s, *t, *u;
+       int     i;
+
+
+       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,
+        * escapted delimiters or '\\'
+       */
+       for (t = s; *t != '\0'; ++t) {
+               if (*t == '\\') {
+                   if (escaped) {      /* convert \\ to \ */
+                       --t;
+                       u = t;
+                       escaped = false;
+                       while (u[0] != '\0') {
+                           u[0] = u[1];
+                           ++u;
+                       }
+                   } else              /* start \-Sequence */
+                       escaped = true;
+                   continue;
+               }
+               
+               /* search for delimiter */
+               for (i=0; delim[i] != '\0'; ++i) {
+                   if (*t == delim[i])
+                       break;
+               }
+               
+               /* un-escaped delimiter found => end of token */
+               if (!escaped && delim[i] != '\0')
+                   break;
+                   
+               /* escaped delimiter found => remove / */
+               if (escaped) {
+                   --t;
+                   u = t;
+                    escaped = false;
+                   while (u[0] != '\0') {
+                       u[0] = u[1];
+                       ++u;
+                   }
+               }
+       }
+
+       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 converts escaped characters:
+ * '\<delim>' -> '<delim>', '\\' -> '\'
+ * 
+ * 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=false;
+       char    *t, *u;
+       int     i;
+       
+       for (t = *s; *t != '\0'; ++t) {
+               if (*t == '\\') {
+                   if (escaped) {      /* convert \\ to \ */
+                       --t;
+                       u = t;
+                       escaped = false;
+                       while (u[0] != '\0') {
+                           u[0] = u[1];
+                           ++u;
+                       }
+                   } else              /* start \-Sequence */
+                       escaped = true;
+                   continue;
+               }
+               
+               /* search for delimiter */
+               for (i=0; delim[i] != '\0'; ++i) {
+                   if (*t == delim[i])
+                       break;
+               }
+               
+               /* un-escaped delimiter found => error */
+               if (!escaped && delim[i] != '\0')
+                       return false;
+
+               /* escaped delimiter found => remove / */
+               if (escaped) {
+                   --t;
+                   u = t;
+                    escaped = false;
+                   while (u[0] != '\0') {
+                       u[0] = u[1];
+                       ++u;
+                   }
+               }
+       }
+       
+       return true;
+}
+
 static int
 fstabscan()
 {
@@ -101,9 +236,19 @@
                ++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");
+                       if (!remove_escapes (&_fs_fstab.fs_spec, " \t"))
+                           goto bad;
                        _fs_fstab.fs_file = strsep(&p, ":\n");
+                       if (!remove_escapes (&_fs_fstab.fs_file, " \t"))
+                           goto bad;
                        fixfsfile();
                        _fs_fstab.fs_type = strsep(&p, ":\n");
                        if (_fs_fstab.fs_type) {
@@ -124,13 +269,15 @@
                        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;
                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;
                fixfsfile();
                while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0')

Attachment: signature.asc
Description: Digital signature

Reply via email to