diff options
author | Lennart Poettering <lennart@poettering.net> | 2015-04-06 20:11:41 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2015-04-07 15:42:25 +0200 |
commit | 527b7a421ff3927d4f3f170b1b143452e88ae1dc (patch) | |
tree | cfb13e123c6dfd547fb005db63a480ca709b46da /src/shared | |
parent | 64f75d7a2898e0c0d2b66f93ddd34ffd345bb3c5 (diff) |
util: rework cunescape(), improve error handling
Change cunescape() to return a normal error code, so that we can
distuingish OOM errors from parse errors.
This also adds a flags parameter to control whether "relaxed" or normal
parsing shall be done. If set no parse failures are generated, and the
only reason why cunescape() can fail is OOM.
Diffstat (limited to 'src/shared')
-rw-r--r-- | src/shared/util.c | 55 | ||||
-rw-r--r-- | src/shared/util.h | 13 |
2 files changed, 44 insertions, 24 deletions
diff --git a/src/shared/util.c b/src/shared/util.c index 8b011ccfa1..67f66ace21 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -1466,12 +1466,13 @@ static int cunescape_one(const char *p, size_t length, char *ret) { return r; } -char *cunescape_length_with_prefix(const char *s, size_t length, const char *prefix) { +int cunescape_length_with_prefix(const char *s, size_t length, const char *prefix, UnescapeFlags flags, char **ret) { char *r, *t; const char *f; size_t pl; assert(s); + assert(ret); /* Undoes C style string escaping, and optionally prefixes it. */ @@ -1479,7 +1480,7 @@ char *cunescape_length_with_prefix(const char *s, size_t length, const char *pre r = new(char, pl+length+1); if (!r) - return NULL; + return -ENOMEM; if (prefix) memcpy(r, prefix, pl); @@ -1491,17 +1492,31 @@ char *cunescape_length_with_prefix(const char *s, size_t length, const char *pre remaining = s + length - f; assert(remaining > 0); - if (*f != '\\' || remaining == 1) { - /* a literal literal, or a trailing backslash, copy verbatim */ + if (*f != '\\') { + /* A literal literal, copy verbatim */ *(t++) = *f; continue; } + if (remaining == 1) { + if (flags & UNESCAPE_RELAX) { + /* A trailing backslash, copy verbatim */ + *(t++) = *f; + continue; + } + + return -EINVAL; + } + k = cunescape_one(f + 1, remaining - 1, t); if (k < 0) { - /* Invalid escape code, let's take it literal then */ - *(t++) = '\\'; - continue; + if (flags & UNESCAPE_RELAX) { + /* Invalid escape code, let's take it literal then */ + *(t++) = '\\'; + continue; + } + + return k; } f += k; @@ -1509,17 +1524,17 @@ char *cunescape_length_with_prefix(const char *s, size_t length, const char *pre } *t = 0; - return r; -} -char *cunescape_length(const char *s, size_t length) { - return cunescape_length_with_prefix(s, length, NULL); + *ret = r; + return t - r; } -char *cunescape(const char *s) { - assert(s); +int cunescape_length(const char *s, size_t length, UnescapeFlags flags, char **ret) { + return cunescape_length_with_prefix(s, length, NULL, flags, ret); +} - return cunescape_length(s, strlen(s)); +int cunescape(const char *s, UnescapeFlags flags, char **ret) { + return cunescape_length(s, strlen(s), flags, ret); } char *xescape(const char *s, const char *bad) { @@ -6731,9 +6746,9 @@ int umount_recursive(const char *prefix, int flags) { continue; } - p = cunescape(path); - if (!p) - return -ENOMEM; + r = cunescape(path, UNESCAPE_RELAX, &p); + if (r < 0) + return r; if (!path_startswith(p, prefix)) continue; @@ -6833,9 +6848,9 @@ int bind_remount_recursive(const char *prefix, bool ro) { continue; } - p = cunescape(path); - if (!p) - return -ENOMEM; + r = cunescape(path, UNESCAPE_RELAX, &p); + if (r < 0) + return r; /* Let's ignore autofs mounts. If they aren't * triggered yet, we want to avoid triggering diff --git a/src/shared/util.h b/src/shared/util.h index 882355665c..e7a5d6366e 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -311,9 +311,14 @@ char decchar(int x) _const_; int undecchar(char c) _const_; char *cescape(const char *s); -char *cunescape(const char *s); -char *cunescape_length(const char *s, size_t length); -char *cunescape_length_with_prefix(const char *s, size_t length, const char *prefix); + +typedef enum UnescapeFlags { + UNESCAPE_RELAX = 1, +} UnescapeFlags; + +int cunescape(const char *s, UnescapeFlags flags, char **ret); +int cunescape_length(const char *s, size_t length, UnescapeFlags flags, char **ret); +int cunescape_length_with_prefix(const char *s, size_t length, const char *prefix, UnescapeFlags flags, char **ret); char *xescape(const char *s, const char *bad); @@ -1014,7 +1019,7 @@ int take_password_lock(const char *root); int is_symlink(const char *path); int is_dir(const char *path, bool follow); -typedef enum UnquoteFlags{ +typedef enum UnquoteFlags { UNQUOTE_RELAX = 1, UNQUOTE_CUNESCAPE = 2, } UnquoteFlags; |