[patch] Re: getfsent(3) and spaces in fstab
Simon Barner
barner at in.tum.de
Sun Aug 3 17:33:40 PDT 2003
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
-------------- next part --------------
--- 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')
-------------- 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/20030804/4c566150/attachment.bin
More information about the freebsd-hackers
mailing list