summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libudev/util.c100
-rw-r--r--src/libudev/util.h8
-rw-r--r--src/udev/udevd.c6
3 files changed, 50 insertions, 64 deletions
diff --git a/src/libudev/util.c b/src/libudev/util.c
index 116d723a0f..5ff767b6a7 100644
--- a/src/libudev/util.c
+++ b/src/libudev/util.c
@@ -263,79 +263,63 @@ int safe_atolli(const char *s, long long int *ret_lli) {
return 0;
}
+static size_t strcspn_escaped(const char *s, const char *reject) {
+ bool escaped = false;
+ size_t n;
+
+ for (n=0; s[n]; n++) {
+ if (escaped)
+ escaped = false;
+ else if (s[n] == '\\')
+ escaped = true;
+ else if (strchr(reject, s[n]))
+ break;
+ }
+ /* if s ends in \, return index of previous char */
+ return n - escaped;
+}
+
/* Split a string into words. */
-char *split(const char *c, size_t *l, const char *separator, char **state) {
- char *current;
+const char* split(const char **state, size_t *l, const char *separator, bool quoted) {
+ const char *current;
- current = *state ? *state : (char*) c;
+ current = *state;
- if (!*current || *c == 0)
+ if (!*current) {
+ assert(**state == '\0');
return NULL;
+ }
current += strspn(current, separator);
- *l = strcspn(current, separator);
- *state = current+*l;
-
- return (char*) current;
-}
-
-/* Split a string into words, but consider strings enclosed in '' and
- * "" as words even if they include spaces. */
-char *split_quoted(const char *c, size_t *l, char **state) {
- char *current, *e;
- bool escaped = false;
-
- current = *state ? *state : (char*) c;
-
- if (!*current || *c == 0)
+ if (!*current) {
+ *state = current;
return NULL;
+ }
- current += strspn(current, WHITESPACE);
-
- if (*current == '\'') {
- current ++;
+ if (quoted && strchr("\'\"", *current)) {
+ char quotechars[2] = {*current, '\0'};
- for (e = current; *e; e++) {
- if (escaped)
- escaped = false;
- else if (*e == '\\')
- escaped = true;
- else if (*e == '\'')
- break;
+ *l = strcspn_escaped(current + 1, quotechars);
+ if (current[*l + 1] == '\0' ||
+ (current[*l + 2] && !strchr(separator, current[*l + 2]))) {
+ /* right quote missing or garbage at the end*/
+ *state = current;
+ return NULL;
}
-
- *l = e-current;
- *state = *e == 0 ? e : e+1;
- } else if (*current == '\"') {
- current ++;
-
- for (e = current; *e; e++) {
- if (escaped)
- escaped = false;
- else if (*e == '\\')
- escaped = true;
- else if (*e == '\"')
- break;
- }
-
- *l = e-current;
- *state = *e == 0 ? e : e+1;
+ assert(current[*l + 1] == quotechars[0]);
+ *state = current++ + *l + 2;
+ } else if (quoted) {
+ *l = strcspn_escaped(current, separator);
+ *state = current + *l;
} else {
- for (e = current; *e; e++) {
- if (escaped)
- escaped = false;
- else if (*e == '\\')
- escaped = true;
- else if (strchr(WHITESPACE, *e))
- break;
- }
- *l = e-current;
- *state = e;
+ *l = strcspn(current, separator);
+ *state = current + *l;
}
- return (char*) current;
+ return current;
}
+
char *truncate_nl(char *s) {
assert(s);
diff --git a/src/libudev/util.h b/src/libudev/util.h
index a38e8e61c5..15a11cc537 100644
--- a/src/libudev/util.h
+++ b/src/libudev/util.h
@@ -134,11 +134,13 @@ int safe_atoi(const char *s, int *ret_i);
int safe_atollu(const char *s, unsigned long long *ret_u);
int safe_atolli(const char *s, long long int *ret_i);
-char *split(const char *c, size_t *l, const char *separator, char **state);
-char *split_quoted(const char *c, size_t *l, char **state);
+const char* split(const char **state, size_t *l, const char *separator, bool quoted);
#define FOREACH_WORD_QUOTED(word, length, s, state) \
- for ((state) = NULL, (word) = split_quoted((s), &(length), &(state)); (word); (word) = split_quoted((s), &(length), &(state)))
+ _FOREACH_WORD(word, length, s, WHITESPACE, true, state)
+
+#define _FOREACH_WORD(word, length, s, separator, quoted, state) \
+ for ((state) = (s), (word) = split(&(state), &(length), (separator), (quoted)); (word); (word) = split(&(state), &(length), (separator), (quoted)))
char *strappend(const char *s, const char *suffix);
char *strnappend(const char *s, const char *suffix, size_t length);
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index f59de08a0e..385bb7edad 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -991,7 +991,7 @@ static void static_dev_create_from_modules(struct udev *udev) {
*/
static void kernel_cmdline_options(struct udev *udev) {
_cleanup_free_ char *line = NULL;
- char *w, *state;
+ const char *word, *state;
size_t l;
int r;
@@ -1001,10 +1001,10 @@ static void kernel_cmdline_options(struct udev *udev) {
if (r <= 0)
return;
- FOREACH_WORD_QUOTED(w, l, line, state) {
+ FOREACH_WORD_QUOTED(word, l, line, state) {
char *s, *opt;
- s = strndup(w, l);
+ s = strndup(word, l);
if (!s)
break;