X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fshared%2Funit-name.c;h=4b52f7bc53a581a0944b92e24e27b6068494ee08;hb=ac7019f33f1618f5b69ed44a8623e2596f1e3856;hp=566cdc51cce4feb2204dafecf3e0b38dfc0aa6c3;hpb=f33d3ec1d7521c91da8b30ad5cb345d6416bb07d;p=elogind.git diff --git a/src/shared/unit-name.c b/src/shared/unit-name.c index 566cdc51c..4b52f7bc5 100644 --- a/src/shared/unit-name.c +++ b/src/shared/unit-name.c @@ -23,6 +23,7 @@ #include #include +#include "path-util.h" #include "util.h" #include "unit-name.h" @@ -111,7 +112,8 @@ int unit_name_to_instance(const char *n, char **instance) { assert(instance); /* Everything past the first @ and before the last . is the instance */ - if (!(p = strchr(n, '@'))) { + p = strchr(n, '@'); + if (!p) { *instance = NULL; return 0; } @@ -119,7 +121,8 @@ int unit_name_to_instance(const char *n, char **instance) { assert_se(d = strrchr(n, '.')); assert(p < d); - if (!(i = strndup(p+1, d-p-1))) + i = strndup(p+1, d-p-1); + if (!i) return -ENOMEM; *instance = i; @@ -139,7 +142,8 @@ char *unit_name_to_prefix_and_instance(const char *n) { char *unit_name_to_prefix(const char *n) { const char *p; - if ((p = strchr(n, '@'))) + p = strchr(n, '@'); + if (p) return strndup(n, p - n); return unit_name_to_prefix_and_instance(n); @@ -157,7 +161,8 @@ char *unit_name_change_suffix(const char *n, const char *suffix) { a = e - n; b = strlen(suffix); - if (!(r = new(char, a + b + 1))) + r = new(char, a + b + 1); + if (!r) return NULL; memcpy(r, n, a); @@ -178,79 +183,47 @@ char *unit_name_build(const char *prefix, const char *instance, const char *suff return join(prefix, "@", instance, suffix, NULL); } -static char* do_escape(const char *f, char *t) { +static char *do_escape_char(char c, char *t) { + *(t++) = '\\'; + *(t++) = 'x'; + *(t++) = hexchar(c >> 4); + *(t++) = hexchar(c); + return t; +} + +static char *do_escape(const char *f, char *t) { assert(f); assert(t); + /* do not create units with a leading '.', like for "/.dotdir" mount points */ + if (*f == '.') { + t = do_escape_char(*f, t); + f++; + } + for (; *f; f++) { if (*f == '/') *(t++) = '-'; - else if (*f == '-' || *f == '\\' || !strchr(VALID_CHARS, *f)) { - *(t++) = '\\'; - *(t++) = 'x'; - *(t++) = hexchar(*f >> 4); - *(t++) = hexchar(*f); - } else + else if (*f == '-' || *f == '\\' || !strchr(VALID_CHARS, *f)) + t = do_escape_char(*f, t); + else *(t++) = *f; } return t; } -char *unit_name_build_escape(const char *prefix, const char *instance, const char *suffix) { - char *r, *t; - size_t a, b, c; - - assert(prefix); - assert(suffix); - - /* Takes a arbitrary string for prefix and instance plus a - * suffix and makes a nice string suitable as unit name of it, - * escaping all weird chars on the way. - * - * / becomes ., and all chars not allowed in a unit name get - * escaped as \xFF, including \ and ., of course. This - * escaping is hence reversible. - * - * This is primarily useful to make nice unit names from - * strings, but is actually useful for any kind of string. - */ - - a = strlen(prefix); - c = strlen(suffix); - - if (instance) { - b = strlen(instance); - - if (!(r = new(char, a*4 + 1 + b*4 + c + 1))) - return NULL; - - t = do_escape(prefix, r); - *(t++) = '@'; - t = do_escape(instance, t); - } else { - - if (!(r = new(char, a*4 + c + 1))) - return NULL; - - t = do_escape(prefix, r); - } - - strcpy(t, suffix); - return r; -} - char *unit_name_escape(const char *f) { char *r, *t; - if (!(r = new(char, strlen(f)*4+1))) + r = new(char, strlen(f)*4+1); + if (!r) return NULL; t = do_escape(f, r); *t = 0; return r; - } char *unit_name_unescape(const char *f) { @@ -258,7 +231,8 @@ char *unit_name_unescape(const char *f) { assert(f); - if (!(r = strdup(f))) + r = strdup(f); + if (!r) return NULL; for (t = r; *f; f++) { @@ -285,6 +259,49 @@ char *unit_name_unescape(const char *f) { return r; } +char *unit_name_path_escape(const char *f) { + char *p, *e; + + assert(f); + + p = strdup(f); + if (!p) + return NULL; + + path_kill_slashes(p); + + if (streq(p, "/")) { + free(p); + return strdup("-"); + } + + e = unit_name_escape(p[0] == '/' ? p + 1 : p); + free(p); + + return e; +} + +char *unit_name_path_unescape(const char *f) { + char *e; + + assert(f); + + e = unit_name_unescape(f); + if (!e) + return NULL; + + if (e[0] != '/') { + char *w; + + w = strappend("/", e); + free(e); + + return w; + } + + return e; +} + bool unit_name_is_template(const char *n) { const char *p; @@ -313,14 +330,16 @@ char *unit_name_replace_instance(const char *f, const char *i) { b = strlen(i); - if (!(r = new(char, a + 1 + b + strlen(e) + 1))) + r = new(char, a + 1 + b + strlen(e) + 1); + if (!r) return NULL; k = mempcpy(r, f, a + 1); k = mempcpy(k, i, b); } else { - if (!(r = new(char, a + strlen(e) + 1))) + r = new(char, a + strlen(e) + 1); + if (!r) return NULL; k = mempcpy(r, f, a); @@ -335,13 +354,15 @@ char *unit_name_template(const char *f) { char *r; size_t a; - if (!(p = strchr(f, '@'))) + p = strchr(f, '@'); + if (!p) return strdup(f); assert_se(e = strrchr(f, '.')); a = p - f + 1; - if (!(r = new(char, a + strlen(e) + 1))) + r = new(char, a + strlen(e) + 1); + if (!r) return NULL; strcpy(mempcpy(r, f, a), e); @@ -355,19 +376,11 @@ char *unit_name_from_path(const char *path, const char *suffix) { assert(path); assert(suffix); - if (!(p = strdup(path))) + p = unit_name_path_escape(path); + if (!p) return NULL; - path_kill_slashes(p); - - path = p[0] == '/' ? p + 1 : p; - - if (path[0] == 0) { - free(p); - return strappend("-", suffix); - } - - r = unit_name_build_escape(path, NULL, suffix); + r = strappend(p, suffix); free(p); return r; @@ -376,22 +389,15 @@ char *unit_name_from_path(const char *path, const char *suffix) { char *unit_name_from_path_instance(const char *prefix, const char *path, const char *suffix) { char *p, *r; + assert(prefix); assert(path); assert(suffix); - if (!(p = strdup(path))) + p = unit_name_path_escape(path); + if (!p) return NULL; - path_kill_slashes(p); - - path = p[0] == '/' ? p + 1 : p; - - if (path[0] == 0) { - free(p); - return unit_name_build_escape(prefix, "-", suffix); - } - - r = unit_name_build_escape(prefix, path, suffix); + r = join(prefix, "@", p, suffix, NULL); free(p); return r; @@ -402,47 +408,65 @@ char *unit_name_to_path(const char *name) { assert(name); - if (!(w = unit_name_to_prefix(name))) + w = unit_name_to_prefix(name); + if (!w) return NULL; - e = unit_name_unescape(w); + e = unit_name_path_unescape(w); free(w); + return e; +} + +char *unit_dbus_path_from_name(const char *name) { + char *e, *p; + + assert(name); + + e = bus_path_escape(name); if (!e) return NULL; - if (e[0] != '/') { - w = strappend("/", e); - free(e); + p = strappend("/org/freedesktop/systemd1/unit/", e); + free(e); - if (!w) - return NULL; + return p; +} - e = w; - } +char *unit_name_mangle(const char *name) { + char *r, *t; + const char *f; - return e; -} + assert(name); -char *unit_name_path_unescape(const char *f) { - char *e; + /* Try to turn a string that might not be a unit name into a + * sensible unit name. */ - assert(f); + if (path_startswith(name, "/dev/") || + path_startswith(name, "/sys/")) + return unit_name_from_path(name, ".device"); - if (!(e = unit_name_unescape(f))) - return NULL; + if (path_is_absolute(name)) + return unit_name_from_path(name, ".mount"); - if (e[0] != '/') { - char *w; + /* We'll only escape the obvious characters here, to play + * safe. */ - w = strappend("/", e); - free(e); + r = new(char, strlen(name) * 4 + 1); + if (!r) + return NULL; - if (!w) - return NULL; + for (f = name, t = r; *f; f++) { - e = w; + if (*f == '/') + *(t++) = '-'; + else if (!strchr("@" VALID_CHARS, *f)) + t = do_escape_char(*f, t); + else + *(t++) = *f; } - return e; + *t = 0; + + return r; }