diff options
Diffstat (limited to 'src/basic')
-rw-r--r-- | src/basic/escape.c | 28 | ||||
-rw-r--r-- | src/basic/escape.h | 1 | ||||
-rw-r--r-- | src/basic/fdset.c | 13 | ||||
-rw-r--r-- | src/basic/fdset.h | 1 | ||||
-rw-r--r-- | src/basic/fs-util.c | 18 | ||||
-rw-r--r-- | src/basic/fs-util.h | 1 | ||||
-rw-r--r-- | src/basic/hexdecoct.c | 3 | ||||
-rw-r--r-- | src/basic/json.c | 871 | ||||
-rw-r--r-- | src/basic/json.h | 90 | ||||
l--------- | src/basic/linux/Makefile | 1 | ||||
-rw-r--r-- | src/basic/mempool.h | 2 | ||||
-rw-r--r-- | src/basic/missing.h | 1 | ||||
-rw-r--r-- | src/basic/strv.c | 4 | ||||
-rw-r--r-- | src/basic/time-util.c | 24 | ||||
-rw-r--r-- | src/basic/util.h | 10 |
15 files changed, 67 insertions, 1001 deletions
diff --git a/src/basic/escape.c b/src/basic/escape.c index 2e483880c8..01daf11ce7 100644 --- a/src/basic/escape.c +++ b/src/basic/escape.c @@ -413,6 +413,34 @@ char *xescape(const char *s, const char *bad) { return r; } +char *octescape(const char *s, size_t len) { + char *r, *t; + const char *f; + + /* Escapes all chars in bad, in addition to \ and " chars, + * in \nnn style escaping. */ + + r = new(char, len * 4 + 1); + if (!r) + return NULL; + + for (f = s, t = r; f < s + len; f++) { + + if (*f < ' ' || *f >= 127 || *f == '\\' || *f == '"') { + *(t++) = '\\'; + *(t++) = '0' + (*f >> 6); + *(t++) = '0' + ((*f >> 3) & 8); + *(t++) = '0' + (*f & 8); + } else + *(t++) = *f; + } + + *t = 0; + + return r; + +} + static char *strcpy_backslash_escaped(char *t, const char *s, const char *bad) { assert(bad); diff --git a/src/basic/escape.h b/src/basic/escape.h index 1b28bd10af..deaa4def28 100644 --- a/src/basic/escape.h +++ b/src/basic/escape.h @@ -48,6 +48,7 @@ int cunescape_length_with_prefix(const char *s, size_t length, const char *prefi int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit); char *xescape(const char *s, const char *bad); +char *octescape(const char *s, size_t len); char *shell_escape(const char *s, const char *bad); char *shell_maybe_quote(const char *s); diff --git a/src/basic/fdset.c b/src/basic/fdset.c index 3674d3ed9d..06f8ecbdbc 100644 --- a/src/basic/fdset.c +++ b/src/basic/fdset.c @@ -94,19 +94,6 @@ int fdset_put(FDSet *s, int fd) { return set_put(MAKE_SET(s), FD_TO_PTR(fd)); } -int fdset_consume(FDSet *s, int fd) { - int r; - - assert(s); - assert(fd >= 0); - - r = fdset_put(s, fd); - if (r <= 0) - safe_close(fd); - - return r; -} - int fdset_put_dup(FDSet *s, int fd) { int copy, r; diff --git a/src/basic/fdset.h b/src/basic/fdset.h index 12d0cef761..16efe5bdf2 100644 --- a/src/basic/fdset.h +++ b/src/basic/fdset.h @@ -32,7 +32,6 @@ FDSet* fdset_free(FDSet *s); int fdset_put(FDSet *s, int fd); int fdset_put_dup(FDSet *s, int fd); -int fdset_consume(FDSet *s, int fd); bool fdset_contains(FDSet *s, int fd); int fdset_remove(FDSet *s, int fd); diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index 3ef1b90edd..51268828af 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -283,24 +283,6 @@ int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) { return 0; } -int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) { - assert(fd >= 0); - - /* Under the assumption that we are running privileged we - * first change the access mode and only then hand out - * ownership to avoid a window where access is too open. */ - - if (mode != MODE_INVALID) - if (fchmod(fd, mode) < 0) - return -errno; - - if (uid != UID_INVALID || gid != GID_INVALID) - if (fchown(fd, uid, gid) < 0) - return -errno; - - return 0; -} - int fchmod_umask(int fd, mode_t m) { mode_t u; int r; diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h index 0e2fcb21b9..0d23f8635f 100644 --- a/src/basic/fs-util.h +++ b/src/basic/fs-util.h @@ -43,7 +43,6 @@ int readlink_and_canonicalize(const char *p, char **r); int readlink_and_make_absolute_root(const char *root, const char *path, char **ret); int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid); -int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid); int fchmod_umask(int fd, mode_t mode); diff --git a/src/basic/hexdecoct.c b/src/basic/hexdecoct.c index 592df53cb5..d7ad8d41f2 100644 --- a/src/basic/hexdecoct.c +++ b/src/basic/hexdecoct.c @@ -25,6 +25,7 @@ #include "alloc-util.h" #include "hexdecoct.h" #include "macro.h" +#include "util.h" char octchar(int x) { return '0' + (x & 7); @@ -572,7 +573,7 @@ static int base64_append_width(char **prefix, int plen, if (!t) return -ENOMEM; - memcpy(t + plen, sep, slen); + memcpy_safe(t + plen, sep, slen); for (line = 0, s = t + plen + slen, avail = len; line < lines; line++) { int act = MIN(width, avail); diff --git a/src/basic/json.c b/src/basic/json.c deleted file mode 100644 index daa98fc815..0000000000 --- a/src/basic/json.c +++ /dev/null @@ -1,871 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2014 Lennart Poettering - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <errno.h> -#include <math.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> - -#include "alloc-util.h" -#include "hexdecoct.h" -#include "json.h" -#include "macro.h" -#include "string-util.h" -#include "utf8.h" - -int json_variant_new(JsonVariant **ret, JsonVariantType type) { - JsonVariant *v; - - v = new0(JsonVariant, 1); - if (!v) - return -ENOMEM; - v->type = type; - *ret = v; - return 0; -} - -static int json_variant_deep_copy(JsonVariant *ret, JsonVariant *variant) { - int r; - - assert(ret); - assert(variant); - - ret->type = variant->type; - ret->size = variant->size; - - if (variant->type == JSON_VARIANT_STRING) { - ret->string = memdup(variant->string, variant->size+1); - if (!ret->string) - return -ENOMEM; - } else if (variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT) { - size_t i; - - ret->objects = new0(JsonVariant, variant->size); - if (!ret->objects) - return -ENOMEM; - - for (i = 0; i < variant->size; ++i) { - r = json_variant_deep_copy(&ret->objects[i], &variant->objects[i]); - if (r < 0) - return r; - } - } else - ret->value = variant->value; - - return 0; -} - -static JsonVariant *json_object_unref(JsonVariant *variant); - -static JsonVariant *json_variant_unref_inner(JsonVariant *variant) { - if (!variant) - return NULL; - - if (variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT) - return json_object_unref(variant); - else if (variant->type == JSON_VARIANT_STRING) - free(variant->string); - - return NULL; -} - -static JsonVariant *json_raw_unref(JsonVariant *variant, size_t size) { - if (!variant) - return NULL; - - for (size_t i = 0; i < size; ++i) - json_variant_unref_inner(&variant[i]); - - free(variant); - return NULL; -} - -static JsonVariant *json_object_unref(JsonVariant *variant) { - size_t i; - - assert(variant); - - if (!variant->objects) - return NULL; - - for (i = 0; i < variant->size; ++i) - json_variant_unref_inner(&variant->objects[i]); - - free(variant->objects); - return NULL; -} - -static JsonVariant **json_variant_array_unref(JsonVariant **variant) { - size_t i = 0; - JsonVariant *p = NULL; - - if (!variant) - return NULL; - - while((p = (variant[i++])) != NULL) { - if (p->type == JSON_VARIANT_STRING) - free(p->string); - free(p); - } - - free(variant); - - return NULL; -} - -DEFINE_TRIVIAL_CLEANUP_FUNC(JsonVariant **, json_variant_array_unref); - -JsonVariant *json_variant_unref(JsonVariant *variant) { - if (!variant) - return NULL; - - if (variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT) - json_object_unref(variant); - else if (variant->type == JSON_VARIANT_STRING) - free(variant->string); - - free(variant); - - return NULL; -} - -char *json_variant_string(JsonVariant *variant){ - assert(variant); - assert(variant->type == JSON_VARIANT_STRING); - - return variant->string; -} - -bool json_variant_bool(JsonVariant *variant) { - assert(variant); - assert(variant->type == JSON_VARIANT_BOOLEAN); - - return variant->value.boolean; -} - -intmax_t json_variant_integer(JsonVariant *variant) { - assert(variant); - assert(variant->type == JSON_VARIANT_INTEGER); - - return variant->value.integer; -} - -double json_variant_real(JsonVariant *variant) { - assert(variant); - assert(variant->type == JSON_VARIANT_REAL); - - return variant->value.real; -} - -JsonVariant *json_variant_element(JsonVariant *variant, unsigned index) { - assert(variant); - assert(variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT); - assert(index < variant->size); - assert(variant->objects); - - return &variant->objects[index]; -} - -JsonVariant *json_variant_value(JsonVariant *variant, const char *key) { - size_t i; - - assert(variant); - assert(variant->type == JSON_VARIANT_OBJECT); - assert(variant->objects); - - for (i = 0; i < variant->size; i += 2) { - JsonVariant *p = &variant->objects[i]; - if (p->type == JSON_VARIANT_STRING && streq(key, p->string)) - return &variant->objects[i + 1]; - } - - return NULL; -} - -static void inc_lines(unsigned *line, const char *s, size_t n) { - const char *p = s; - - if (!line) - return; - - for (;;) { - const char *f; - - f = memchr(p, '\n', n); - if (!f) - return; - - n -= (f - p) + 1; - p = f + 1; - (*line)++; - } -} - -static int unhex_ucs2(const char *c, uint16_t *ret) { - int aa, bb, cc, dd; - uint16_t x; - - assert(c); - assert(ret); - - aa = unhexchar(c[0]); - if (aa < 0) - return -EINVAL; - - bb = unhexchar(c[1]); - if (bb < 0) - return -EINVAL; - - cc = unhexchar(c[2]); - if (cc < 0) - return -EINVAL; - - dd = unhexchar(c[3]); - if (dd < 0) - return -EINVAL; - - x = ((uint16_t) aa << 12) | - ((uint16_t) bb << 8) | - ((uint16_t) cc << 4) | - ((uint16_t) dd); - - if (x <= 0) - return -EINVAL; - - *ret = x; - - return 0; -} - -static int json_parse_string(const char **p, char **ret) { - _cleanup_free_ char *s = NULL; - size_t n = 0, allocated = 0; - const char *c; - - assert(p); - assert(*p); - assert(ret); - - c = *p; - - if (*c != '"') - return -EINVAL; - - c++; - - for (;;) { - int len; - - /* Check for EOF */ - if (*c == 0) - return -EINVAL; - - /* Check for control characters 0x00..0x1f */ - if (*c > 0 && *c < ' ') - return -EINVAL; - - /* Check for control character 0x7f */ - if (*c == 0x7f) - return -EINVAL; - - if (*c == '"') { - if (!s) { - s = strdup(""); - if (!s) - return -ENOMEM; - } else - s[n] = 0; - - *p = c + 1; - - *ret = s; - s = NULL; - return JSON_STRING; - } - - if (*c == '\\') { - char ch = 0; - c++; - - if (*c == 0) - return -EINVAL; - - if (IN_SET(*c, '"', '\\', '/')) - ch = *c; - else if (*c == 'b') - ch = '\b'; - else if (*c == 'f') - ch = '\f'; - else if (*c == 'n') - ch = '\n'; - else if (*c == 'r') - ch = '\r'; - else if (*c == 't') - ch = '\t'; - else if (*c == 'u') { - char16_t x; - int r; - - r = unhex_ucs2(c + 1, &x); - if (r < 0) - return r; - - c += 5; - - if (!GREEDY_REALLOC(s, allocated, n + 4)) - return -ENOMEM; - - if (!utf16_is_surrogate(x)) - n += utf8_encode_unichar(s + n, (char32_t) x); - else if (utf16_is_trailing_surrogate(x)) - return -EINVAL; - else { - char16_t y; - - if (c[0] != '\\' || c[1] != 'u') - return -EINVAL; - - r = unhex_ucs2(c + 2, &y); - if (r < 0) - return r; - - c += 6; - - if (!utf16_is_trailing_surrogate(y)) - return -EINVAL; - - n += utf8_encode_unichar(s + n, utf16_surrogate_pair_to_unichar(x, y)); - } - - continue; - } else - return -EINVAL; - - if (!GREEDY_REALLOC(s, allocated, n + 2)) - return -ENOMEM; - - s[n++] = ch; - c ++; - continue; - } - - len = utf8_encoded_valid_unichar(c); - if (len < 0) - return len; - - if (!GREEDY_REALLOC(s, allocated, n + len + 1)) - return -ENOMEM; - - memcpy(s + n, c, len); - n += len; - c += len; - } -} - -static int json_parse_number(const char **p, union json_value *ret) { - bool negative = false, exponent_negative = false, is_double = false; - double x = 0.0, y = 0.0, exponent = 0.0, shift = 1.0; - intmax_t i = 0; - const char *c; - - assert(p); - assert(*p); - assert(ret); - - c = *p; - - if (*c == '-') { - negative = true; - c++; - } - - if (*c == '0') - c++; - else { - if (!strchr("123456789", *c) || *c == 0) - return -EINVAL; - - do { - if (!is_double) { - int64_t t; - - t = 10 * i + (*c - '0'); - if (t < i) /* overflow */ - is_double = false; - else - i = t; - } - - x = 10.0 * x + (*c - '0'); - c++; - } while (strchr("0123456789", *c) && *c != 0); - } - - if (*c == '.') { - is_double = true; - c++; - - if (!strchr("0123456789", *c) || *c == 0) - return -EINVAL; - - do { - y = 10.0 * y + (*c - '0'); - shift = 10.0 * shift; - c++; - } while (strchr("0123456789", *c) && *c != 0); - } - - if (*c == 'e' || *c == 'E') { - is_double = true; - c++; - - if (*c == '-') { - exponent_negative = true; - c++; - } else if (*c == '+') - c++; - - if (!strchr("0123456789", *c) || *c == 0) - return -EINVAL; - - do { - exponent = 10.0 * exponent + (*c - '0'); - c++; - } while (strchr("0123456789", *c) && *c != 0); - } - - *p = c; - - if (is_double) { - ret->real = ((negative ? -1.0 : 1.0) * (x + (y / shift))) * exp10((exponent_negative ? -1.0 : 1.0) * exponent); - return JSON_REAL; - } else { - ret->integer = negative ? -i : i; - return JSON_INTEGER; - } -} - -int json_tokenize( - const char **p, - char **ret_string, - union json_value *ret_value, - void **state, - unsigned *line) { - - const char *c; - int t; - int r; - - enum { - STATE_NULL, - STATE_VALUE, - STATE_VALUE_POST, - }; - - assert(p); - assert(*p); - assert(ret_string); - assert(ret_value); - assert(state); - - t = PTR_TO_INT(*state); - c = *p; - - if (t == STATE_NULL) { - if (line) - *line = 1; - t = STATE_VALUE; - } - - for (;;) { - const char *b; - - b = c + strspn(c, WHITESPACE); - if (*b == 0) - return JSON_END; - - inc_lines(line, c, b - c); - c = b; - - switch (t) { - - case STATE_VALUE: - - if (*c == '{') { - *ret_string = NULL; - *ret_value = JSON_VALUE_NULL; - *p = c + 1; - *state = INT_TO_PTR(STATE_VALUE); - return JSON_OBJECT_OPEN; - - } else if (*c == '}') { - *ret_string = NULL; - *ret_value = JSON_VALUE_NULL; - *p = c + 1; - *state = INT_TO_PTR(STATE_VALUE_POST); - return JSON_OBJECT_CLOSE; - - } else if (*c == '[') { - *ret_string = NULL; - *ret_value = JSON_VALUE_NULL; - *p = c + 1; - *state = INT_TO_PTR(STATE_VALUE); - return JSON_ARRAY_OPEN; - - } else if (*c == ']') { - *ret_string = NULL; - *ret_value = JSON_VALUE_NULL; - *p = c + 1; - *state = INT_TO_PTR(STATE_VALUE_POST); - return JSON_ARRAY_CLOSE; - - } else if (*c == '"') { - r = json_parse_string(&c, ret_string); - if (r < 0) - return r; - - *ret_value = JSON_VALUE_NULL; - *p = c; - *state = INT_TO_PTR(STATE_VALUE_POST); - return r; - - } else if (strchr("-0123456789", *c)) { - r = json_parse_number(&c, ret_value); - if (r < 0) - return r; - - *ret_string = NULL; - *p = c; - *state = INT_TO_PTR(STATE_VALUE_POST); - return r; - - } else if (startswith(c, "true")) { - *ret_string = NULL; - ret_value->boolean = true; - *p = c + 4; - *state = INT_TO_PTR(STATE_VALUE_POST); - return JSON_BOOLEAN; - - } else if (startswith(c, "false")) { - *ret_string = NULL; - ret_value->boolean = false; - *p = c + 5; - *state = INT_TO_PTR(STATE_VALUE_POST); - return JSON_BOOLEAN; - - } else if (startswith(c, "null")) { - *ret_string = NULL; - *ret_value = JSON_VALUE_NULL; - *p = c + 4; - *state = INT_TO_PTR(STATE_VALUE_POST); - return JSON_NULL; - - } else - return -EINVAL; - - case STATE_VALUE_POST: - - if (*c == ':') { - *ret_string = NULL; - *ret_value = JSON_VALUE_NULL; - *p = c + 1; - *state = INT_TO_PTR(STATE_VALUE); - return JSON_COLON; - } else if (*c == ',') { - *ret_string = NULL; - *ret_value = JSON_VALUE_NULL; - *p = c + 1; - *state = INT_TO_PTR(STATE_VALUE); - return JSON_COMMA; - } else if (*c == '}') { - *ret_string = NULL; - *ret_value = JSON_VALUE_NULL; - *p = c + 1; - *state = INT_TO_PTR(STATE_VALUE_POST); - return JSON_OBJECT_CLOSE; - } else if (*c == ']') { - *ret_string = NULL; - *ret_value = JSON_VALUE_NULL; - *p = c + 1; - *state = INT_TO_PTR(STATE_VALUE_POST); - return JSON_ARRAY_CLOSE; - } else - return -EINVAL; - } - - } -} - -static bool json_is_value(JsonVariant *var) { - assert(var); - - return var->type != JSON_VARIANT_CONTROL; -} - -static int json_scoped_parse(JsonVariant **tokens, size_t *i, size_t n, JsonVariant *scope) { - bool arr = scope->type == JSON_VARIANT_ARRAY; - int terminator = arr ? JSON_ARRAY_CLOSE : JSON_OBJECT_CLOSE; - size_t allocated = 0, size = 0; - JsonVariant *key = NULL, *value = NULL, *var = NULL, *items = NULL; - enum { - STATE_KEY, - STATE_COLON, - STATE_COMMA, - STATE_VALUE - } state = arr ? STATE_VALUE : STATE_KEY; - - assert(tokens); - assert(i); - assert(scope); - - while((var = *i < n ? tokens[(*i)++] : NULL) != NULL) { - bool stopper; - int r; - - stopper = !json_is_value(var) && var->value.integer == terminator; - - if (stopper) { - if (state != STATE_COMMA && size > 0) - goto error; - - goto out; - } - - if (state == STATE_KEY) { - if (var->type != JSON_VARIANT_STRING) - goto error; - else { - key = var; - state = STATE_COLON; - } - } - else if (state == STATE_COLON) { - if (key == NULL) - goto error; - - if (json_is_value(var)) - goto error; - - if (var->value.integer != JSON_COLON) - goto error; - - state = STATE_VALUE; - } - else if (state == STATE_VALUE) { - _cleanup_json_variant_unref_ JsonVariant *v = NULL; - size_t toadd = arr ? 1 : 2; - - if (!json_is_value(var)) { - int type = (var->value.integer == JSON_ARRAY_OPEN) ? JSON_VARIANT_ARRAY : JSON_VARIANT_OBJECT; - - r = json_variant_new(&v, type); - if (r < 0) - goto error; - - r = json_scoped_parse(tokens, i, n, v); - if (r < 0) - goto error; - - value = v; - } - else - value = var; - - if(!GREEDY_REALLOC(items, allocated, size + toadd)) - goto error; - - if (arr) { - r = json_variant_deep_copy(&items[size], value); - if (r < 0) - goto error; - } else { - r = json_variant_deep_copy(&items[size], key); - if (r < 0) - goto error; - - r = json_variant_deep_copy(&items[size+1], value); - if (r < 0) - goto error; - } - - size += toadd; - state = STATE_COMMA; - } - else if (state == STATE_COMMA) { - if (json_is_value(var)) - goto error; - - if (var->value.integer != JSON_COMMA) - goto error; - - key = NULL; - value = NULL; - - state = arr ? STATE_VALUE : STATE_KEY; - } - } - -error: - json_raw_unref(items, size); - return -EBADMSG; - -out: - scope->size = size; - scope->objects = items; - - return scope->type; -} - -static int json_parse_tokens(JsonVariant **tokens, size_t ntokens, JsonVariant **rv) { - size_t it = 0; - int r; - JsonVariant *e; - _cleanup_json_variant_unref_ JsonVariant *p = NULL; - - assert(tokens); - assert(ntokens); - - e = tokens[it++]; - r = json_variant_new(&p, JSON_VARIANT_OBJECT); - if (r < 0) - return r; - - if (e->type != JSON_VARIANT_CONTROL && e->value.integer != JSON_OBJECT_OPEN) - return -EBADMSG; - - r = json_scoped_parse(tokens, &it, ntokens, p); - if (r < 0) - return r; - - *rv = p; - p = NULL; - - return 0; -} - -static int json_tokens(const char *string, size_t size, JsonVariant ***tokens, size_t *n) { - _cleanup_free_ char *buf = NULL; - _cleanup_(json_variant_array_unrefp) JsonVariant **items = NULL; - union json_value v = {}; - void *json_state = NULL; - const char *p; - int t, r; - size_t allocated = 0, s = 0; - - assert(string); - assert(n); - - if (size <= 0) - return -EBADMSG; - - buf = strndup(string, size); - if (!buf) - return -ENOMEM; - - p = buf; - for (;;) { - _cleanup_json_variant_unref_ JsonVariant *var = NULL; - _cleanup_free_ char *rstr = NULL; - - t = json_tokenize(&p, &rstr, &v, &json_state, NULL); - - if (t < 0) - return t; - else if (t == JSON_END) - break; - - if (t <= JSON_ARRAY_CLOSE) { - r = json_variant_new(&var, JSON_VARIANT_CONTROL); - if (r < 0) - return r; - var->value.integer = t; - } else { - switch (t) { - case JSON_STRING: - r = json_variant_new(&var, JSON_VARIANT_STRING); - if (r < 0) - return r; - var->size = strlen(rstr); - var->string = strdup(rstr); - if (!var->string) { - return -ENOMEM; - } - break; - case JSON_INTEGER: - r = json_variant_new(&var, JSON_VARIANT_INTEGER); - if (r < 0) - return r; - var->value = v; - break; - case JSON_REAL: - r = json_variant_new(&var, JSON_VARIANT_REAL); - if (r < 0) - return r; - var->value = v; - break; - case JSON_BOOLEAN: - r = json_variant_new(&var, JSON_VARIANT_BOOLEAN); - if (r < 0) - return r; - var->value = v; - break; - case JSON_NULL: - r = json_variant_new(&var, JSON_VARIANT_NULL); - if (r < 0) - return r; - break; - } - } - - if (!GREEDY_REALLOC(items, allocated, s+2)) - return -ENOMEM; - - items[s++] = var; - items[s] = NULL; - var = NULL; - } - - *n = s; - *tokens = items; - items = NULL; - - return 0; -} - -int json_parse(const char *string, JsonVariant **rv) { - _cleanup_(json_variant_array_unrefp) JsonVariant **s = NULL; - JsonVariant *v = NULL; - size_t n = 0; - int r; - - assert(string); - assert(rv); - - r = json_tokens(string, strlen(string), &s, &n); - if (r < 0) - return r; - - r = json_parse_tokens(s, n, &v); - if (r < 0) - return r; - - *rv = v; - return 0; -} diff --git a/src/basic/json.h b/src/basic/json.h deleted file mode 100644 index a4509f680f..0000000000 --- a/src/basic/json.h +++ /dev/null @@ -1,90 +0,0 @@ -#pragma once - -/*** - This file is part of systemd. - - Copyright 2014 Lennart Poettering - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> - -#include "macro.h" -#include "util.h" - -enum { - JSON_END, - JSON_COLON, - JSON_COMMA, - JSON_OBJECT_OPEN, - JSON_OBJECT_CLOSE, - JSON_ARRAY_OPEN, - JSON_ARRAY_CLOSE, - JSON_STRING, - JSON_REAL, - JSON_INTEGER, - JSON_BOOLEAN, - JSON_NULL, -}; - -typedef enum { - JSON_VARIANT_CONTROL, - JSON_VARIANT_STRING, - JSON_VARIANT_INTEGER, - JSON_VARIANT_BOOLEAN, - JSON_VARIANT_REAL, - JSON_VARIANT_ARRAY, - JSON_VARIANT_OBJECT, - JSON_VARIANT_NULL -} JsonVariantType; - -union json_value { - bool boolean; - double real; - intmax_t integer; -}; - -typedef struct JsonVariant { - JsonVariantType type; - size_t size; - union { - char *string; - struct JsonVariant *objects; - union json_value value; - }; -} JsonVariant; - -int json_variant_new(JsonVariant **ret, JsonVariantType type); -JsonVariant *json_variant_unref(JsonVariant *v); - -DEFINE_TRIVIAL_CLEANUP_FUNC(JsonVariant *, json_variant_unref); -#define _cleanup_json_variant_unref_ _cleanup_(json_variant_unrefp) - -char *json_variant_string(JsonVariant *v); -bool json_variant_bool(JsonVariant *v); -intmax_t json_variant_integer(JsonVariant *v); -double json_variant_real(JsonVariant *v); - -JsonVariant *json_variant_element(JsonVariant *v, unsigned index); -JsonVariant *json_variant_value(JsonVariant *v, const char *key); - -#define JSON_VALUE_NULL ((union json_value) {}) - -int json_tokenize(const char **p, char **ret_string, union json_value *ret_value, void **state, unsigned *line); - -int json_parse(const char *string, JsonVariant **rv); -int json_parse_measure(const char *string, size_t *size); diff --git a/src/basic/linux/Makefile b/src/basic/linux/Makefile deleted file mode 120000 index d0b0e8e008..0000000000 --- a/src/basic/linux/Makefile +++ /dev/null @@ -1 +0,0 @@ -../Makefile
\ No newline at end of file diff --git a/src/basic/mempool.h b/src/basic/mempool.h index fea7841bcf..0618b8dd22 100644 --- a/src/basic/mempool.h +++ b/src/basic/mempool.h @@ -36,7 +36,7 @@ void* mempool_alloc0_tile(struct mempool *mp); void mempool_free_tile(struct mempool *mp, void *p); #define DEFINE_MEMPOOL(pool_name, tile_type, alloc_at_least) \ -struct mempool pool_name = { \ +static struct mempool pool_name = { \ .tile_size = sizeof(tile_type), \ .at_least = alloc_at_least, \ } diff --git a/src/basic/missing.h b/src/basic/missing.h index 36b060496a..4d3764c022 100644 --- a/src/basic/missing.h +++ b/src/basic/missing.h @@ -714,6 +714,7 @@ static inline int setns(int fd, int nstype) { #endif #if !HAVE_DECL_IFLA_PHYS_PORT_ID +#define IFLA_EXT_MASK 29 #undef IFLA_PROMISCUITY #define IFLA_PROMISCUITY 30 #define IFLA_NUM_TX_QUEUES 31 diff --git a/src/basic/strv.c b/src/basic/strv.c index b5d4d8191b..8282298dca 100644 --- a/src/basic/strv.c +++ b/src/basic/strv.c @@ -371,7 +371,7 @@ char *strv_join(char **l, const char *separator) { n = 0; STRV_FOREACH(s, l) { - if (n != 0) + if (s != l) n += k; n += strlen(*s); } @@ -382,7 +382,7 @@ char *strv_join(char **l, const char *separator) { e = r; STRV_FOREACH(s, l) { - if (e != r) + if (s != l) e = stpcpy(e, separator); e = stpcpy(e, *s); diff --git a/src/basic/time-util.c b/src/basic/time-util.c index 3973850b44..510f018d9b 100644 --- a/src/basic/time-util.c +++ b/src/basic/time-util.c @@ -42,10 +42,30 @@ static nsec_t timespec_load_nsec(const struct timespec *ts); +static clockid_t map_clock_id(clockid_t c) { + + /* Some more exotic archs (s390, ppc, …) lack the "ALARM" flavour of the clocks. Thus, clock_gettime() will + * fail for them. Since they are essentially the same as their non-ALARM pendants (their only difference is + * when timers are set on them), let's just map them accordingly. This way, we can get the correct time even on + * those archs. */ + + switch (c) { + + case CLOCK_BOOTTIME_ALARM: + return CLOCK_BOOTTIME; + + case CLOCK_REALTIME_ALARM: + return CLOCK_REALTIME; + + default: + return c; + } +} + usec_t now(clockid_t clock_id) { struct timespec ts; - assert_se(clock_gettime(clock_id, &ts) == 0); + assert_se(clock_gettime(map_clock_id(clock_id), &ts) == 0); return timespec_load(&ts); } @@ -53,7 +73,7 @@ usec_t now(clockid_t clock_id) { nsec_t now_nsec(clockid_t clock_id) { struct timespec ts; - assert_se(clock_gettime(clock_id, &ts) == 0); + assert_se(clock_gettime(map_clock_id(clock_id), &ts) == 0); return timespec_load_nsec(&ts); } diff --git a/src/basic/util.h b/src/basic/util.h index 6f42c85a33..e095254b57 100644 --- a/src/basic/util.h +++ b/src/basic/util.h @@ -102,6 +102,16 @@ static inline void qsort_safe(void *base, size_t nmemb, size_t size, comparison_ qsort(base, nmemb, size, compar); } +/** + * Normal memcpy requires src to be nonnull. We do nothing if n is 0. + */ +static inline void memcpy_safe(void *dst, const void *src, size_t n) { + if (n == 0) + return; + assert(src); + memcpy(dst, src, n); +} + int on_ac_power(void); #define memzero(x,l) (memset((x), 0, (l))) |