summaryrefslogtreecommitdiff
path: root/src/basic
diff options
context:
space:
mode:
Diffstat (limited to 'src/basic')
-rw-r--r--src/basic/escape.c28
-rw-r--r--src/basic/escape.h1
-rw-r--r--src/basic/fdset.c13
-rw-r--r--src/basic/fdset.h1
-rw-r--r--src/basic/fs-util.c18
-rw-r--r--src/basic/fs-util.h1
-rw-r--r--src/basic/hexdecoct.c3
-rw-r--r--src/basic/json.c871
-rw-r--r--src/basic/json.h90
l---------src/basic/linux/Makefile1
-rw-r--r--src/basic/mempool.h2
-rw-r--r--src/basic/missing.h1
-rw-r--r--src/basic/strv.c4
-rw-r--r--src/basic/time-util.c24
-rw-r--r--src/basic/util.h10
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)))