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')
signature.asc
Description: Digital signature