summaryrefslogtreecommitdiff
path: root/src/shared
diff options
context:
space:
mode:
Diffstat (limited to 'src/shared')
-rw-r--r--src/shared/architecture.c2
-rw-r--r--src/shared/architecture.h2
-rw-r--r--src/shared/ask-password-api.c2
-rw-r--r--src/shared/base-filesystem.c16
-rw-r--r--src/shared/base-filesystem.h4
-rw-r--r--src/shared/capability.h2
-rw-r--r--src/shared/cgroup-util.c2
-rw-r--r--src/shared/condition.c2
-rw-r--r--src/shared/conf-parser.c2
-rw-r--r--src/shared/dev-setup.c29
-rw-r--r--src/shared/dev-setup.h4
-rw-r--r--src/shared/fdset.c2
-rw-r--r--src/shared/generator.c2
-rw-r--r--src/shared/hostname-util.c33
-rw-r--r--src/shared/hostname-util.h2
-rw-r--r--src/shared/import-util.c21
-rw-r--r--src/shared/import-util.h2
-rw-r--r--src/shared/json.c441
-rw-r--r--src/shared/json.h39
-rw-r--r--src/shared/log.c1
-rw-r--r--src/shared/machine-pool.c3
-rw-r--r--src/shared/missing.h11
-rw-r--r--src/shared/path-util.c34
-rw-r--r--src/shared/path-util.h4
-rw-r--r--src/shared/process-util.c3
-rw-r--r--src/shared/pty.c3
-rw-r--r--src/shared/random-util.c2
-rw-r--r--src/shared/rm-rf.c2
-rw-r--r--src/shared/signal-util.c228
-rw-r--r--src/shared/signal-util.h41
-rw-r--r--src/shared/switch-root.c2
-rw-r--r--src/shared/unit-name.c2
-rw-r--r--src/shared/unit-name.h6
-rw-r--r--src/shared/util.c278
-rw-r--r--src/shared/util.h30
35 files changed, 970 insertions, 289 deletions
diff --git a/src/shared/architecture.c b/src/shared/architecture.c
index 884abdd3ea..8e72e7a36a 100644
--- a/src/shared/architecture.c
+++ b/src/shared/architecture.c
@@ -35,7 +35,7 @@ int uname_architecture(void) {
* 1:1. Instead we try to clean it up and break down the
* confusion on x86 and arm in particular.
*
- * We do not try to distuingish CPUs not CPU features, but
+ * We do not try to distinguish CPUs not CPU features, but
* actual architectures, i.e. that have genuinely different
* code. */
diff --git a/src/shared/architecture.h b/src/shared/architecture.h
index cb82418a5e..f5bbf65a90 100644
--- a/src/shared/architecture.h
+++ b/src/shared/architecture.h
@@ -27,7 +27,7 @@
/* A cleaned up architecture definition. We don't want to get lost in
* processor features, models, generations or even ABIs. Hence we
- * focus on general family, and distuignish word width and
+ * focus on general family, and distinguish word width and
* endianness. */
enum {
diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c
index a3a2e51bb9..ef3788be68 100644
--- a/src/shared/ask-password-api.c
+++ b/src/shared/ask-password-api.c
@@ -37,7 +37,7 @@
#include "strv.h"
#include "random-util.h"
#include "terminal-util.h"
-
+#include "signal-util.h"
#include "ask-password-api.h"
static void backspace_chars(int ttyfd, size_t p) {
diff --git a/src/shared/base-filesystem.c b/src/shared/base-filesystem.c
index 11e0947407..ab6fc171b0 100644
--- a/src/shared/base-filesystem.c
+++ b/src/shared/base-filesystem.c
@@ -41,13 +41,16 @@ static const BaseFilesystem table[] = {
{ "lib", 0, "usr/lib\0", NULL },
{ "root", 0755, NULL, NULL },
{ "sbin", 0, "usr/sbin\0", NULL },
+ { "usr", 0755, NULL, NULL },
+ { "var", 0755, NULL, NULL },
+ { "etc", 0755, NULL, NULL },
#if defined(__i386__) || defined(__x86_64__)
{ "lib64", 0, "usr/lib/x86_64-linux-gnu\0"
"usr/lib64\0", "ld-linux-x86-64.so.2" },
#endif
};
-int base_filesystem_create(const char *root) {
+int base_filesystem_create(const char *root, uid_t uid, gid_t gid) {
_cleanup_close_ int fd = -1;
unsigned i;
int r = 0;
@@ -90,6 +93,12 @@ int base_filesystem_create(const char *root) {
r = symlinkat(target, fd, table[i].dir);
if (r < 0 && errno != EEXIST)
return log_error_errno(errno, "Failed to create symlink at %s/%s: %m", root, table[i].dir);
+
+ if (uid != UID_INVALID || gid != UID_INVALID) {
+ if (fchownat(fd, table[i].dir, uid, gid, AT_SYMLINK_NOFOLLOW) < 0)
+ return log_error_errno(errno, "Failed to chown symlink at %s/%s: %m", root, table[i].dir);
+ }
+
continue;
}
@@ -97,6 +106,11 @@ int base_filesystem_create(const char *root) {
r = mkdirat(fd, table[i].dir, table[i].mode);
if (r < 0 && errno != EEXIST)
return log_error_errno(errno, "Failed to create directory at %s/%s: %m", root, table[i].dir);
+
+ if (uid != UID_INVALID || gid != UID_INVALID) {
+ if (fchownat(fd, table[i].dir, uid, gid, AT_SYMLINK_NOFOLLOW) < 0)
+ return log_error_errno(errno, "Failed to chown directory at %s/%s: %m", root, table[i].dir);
+ }
}
return 0;
diff --git a/src/shared/base-filesystem.h b/src/shared/base-filesystem.h
index 03201f7083..39a496090f 100644
--- a/src/shared/base-filesystem.h
+++ b/src/shared/base-filesystem.h
@@ -21,4 +21,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-int base_filesystem_create(const char *root);
+#include <sys/types.h>
+
+int base_filesystem_create(const char *root, uid_t uid, gid_t gid);
diff --git a/src/shared/capability.h b/src/shared/capability.h
index 8260ae1a81..4eb5c2a835 100644
--- a/src/shared/capability.h
+++ b/src/shared/capability.h
@@ -31,7 +31,7 @@ int have_effective_cap(int value);
int capability_bounding_set_drop(uint64_t drop, bool right_now);
int capability_bounding_set_drop_usermode(uint64_t drop);
-int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilites);
+int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilities);
int drop_capability(cap_value_t cv);
diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c
index c0b0ca4cf2..9988e5c574 100644
--- a/src/shared/cgroup-util.c
+++ b/src/shared/cgroup-util.c
@@ -489,7 +489,7 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch
if (_unlikely_(!good)) {
int r;
- r = path_is_mount_point("/sys/fs/cgroup", false);
+ r = path_is_mount_point("/sys/fs/cgroup", 0);
if (r < 0)
return r;
if (r == 0)
diff --git a/src/shared/condition.c b/src/shared/condition.c
index 9f2574c2f6..24871b0dae 100644
--- a/src/shared/condition.c
+++ b/src/shared/condition.c
@@ -349,7 +349,7 @@ static int condition_test_path_is_mount_point(Condition *c) {
assert(c->parameter);
assert(c->type == CONDITION_PATH_IS_MOUNT_POINT);
- return path_is_mount_point(c->parameter, true) > 0;
+ return path_is_mount_point(c->parameter, AT_SYMLINK_FOLLOW) > 0;
}
static int condition_test_path_is_read_write(Condition *c) {
diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c
index 2c855157a9..7370c786f9 100644
--- a/src/shared/conf-parser.c
+++ b/src/shared/conf-parser.c
@@ -444,7 +444,7 @@ int config_parse_many(const char *conf_file,
if (r < 0) \
log_syntax(unit, LOG_ERR, filename, line, -r, \
"Failed to parse %s value, ignoring: %s", \
- #vartype, rvalue); \
+ #type, rvalue); \
\
return 0; \
}
diff --git a/src/shared/dev-setup.c b/src/shared/dev-setup.c
index cb15da8a5d..25ad918b85 100644
--- a/src/shared/dev-setup.c
+++ b/src/shared/dev-setup.c
@@ -23,13 +23,12 @@
#include <stdlib.h>
#include <unistd.h>
-#include "dev-setup.h"
#include "util.h"
#include "label.h"
+#include "path-util.h"
+#include "dev-setup.h"
-int dev_setup(const char *prefix) {
- const char *j, *k;
-
+int dev_setup(const char *prefix, uid_t uid, gid_t gid) {
static const char symlinks[] =
"-/proc/kcore\0" "/dev/core\0"
"/proc/self/fd\0" "/dev/fd\0"
@@ -37,7 +36,13 @@ int dev_setup(const char *prefix) {
"/proc/self/fd/1\0" "/dev/stdout\0"
"/proc/self/fd/2\0" "/dev/stderr\0";
+ const char *j, *k;
+ int r;
+
NULSTR_FOREACH_PAIR(j, k, symlinks) {
+ _cleanup_free_ char *link_name = NULL;
+ const char *n;
+
if (j[0] == '-') {
j++;
@@ -46,15 +51,21 @@ int dev_setup(const char *prefix) {
}
if (prefix) {
- _cleanup_free_ char *link_name = NULL;
-
- link_name = strjoin(prefix, "/", k, NULL);
+ link_name = prefix_root(prefix, k);
if (!link_name)
return -ENOMEM;
- symlink_label(j, link_name);
+ n = link_name;
} else
- symlink_label(j, k);
+ n = k;
+
+ r = symlink_label(j, n);
+ if (r < 0)
+ log_debug_errno(r, "Failed to symlink %s to %s: %m", j, n);
+
+ if (uid != UID_INVALID || gid != GID_INVALID)
+ if (lchown(n, uid, gid) < 0)
+ log_debug_errno(errno, "Failed to chown %s: %m", n);
}
return 0;
diff --git a/src/shared/dev-setup.h b/src/shared/dev-setup.h
index d41b6eefba..ab2748db7f 100644
--- a/src/shared/dev-setup.h
+++ b/src/shared/dev-setup.h
@@ -21,4 +21,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-int dev_setup(const char *pathprefix);
+#include <sys/types.h>
+
+int dev_setup(const char *prefix, uid_t uid, gid_t gid);
diff --git a/src/shared/fdset.c b/src/shared/fdset.c
index 31849272bd..6101b628ec 100644
--- a/src/shared/fdset.c
+++ b/src/shared/fdset.c
@@ -32,7 +32,7 @@
#define MAKE_SET(s) ((Set*) s)
#define MAKE_FDSET(s) ((FDSet*) s)
-/* Make sure we can distuingish fd 0 and NULL */
+/* Make sure we can distinguish fd 0 and NULL */
#define FD_TO_PTR(fd) INT_TO_PTR((fd)+1)
#define PTR_TO_FD(p) (PTR_TO_INT(p)-1)
diff --git a/src/shared/generator.c b/src/shared/generator.c
index 81284995f5..807569a1b8 100644
--- a/src/shared/generator.c
+++ b/src/shared/generator.c
@@ -61,7 +61,7 @@ static int write_fsck_sysroot_service(const char *dir, const char *what) {
"[Service]\n"
"Type=oneshot\n"
"RemainAfterExit=yes\n"
- "ExecStart=/usr/lib/systemd/systemd-fsck %2$s\n"
+ "ExecStart=" SYSTEMD_FSCK_PATH " %2$s\n"
"TimeoutSec=0\n",
program_invocation_short_name,
what,
diff --git a/src/shared/hostname-util.c b/src/shared/hostname-util.c
index 2998fdf2c7..e336f269fa 100644
--- a/src/shared/hostname-util.c
+++ b/src/shared/hostname-util.c
@@ -158,3 +158,36 @@ int sethostname_idempotent(const char *s) {
return 1;
}
+
+int read_hostname_config(const char *path, char **hostname) {
+ _cleanup_fclose_ FILE *f = NULL;
+ char l[LINE_MAX];
+ char *name = NULL;
+
+ assert(path);
+ assert(hostname);
+
+ f = fopen(path, "re");
+ if (!f)
+ return -errno;
+
+ /* may have comments, ignore them */
+ FOREACH_LINE(l, f, return -errno) {
+ truncate_nl(l);
+ if (l[0] != '\0' && l[0] != '#') {
+ /* found line with value */
+ name = hostname_cleanup(l, false);
+ name = strdup(name);
+ if (!name)
+ return -ENOMEM;
+ break;
+ }
+ }
+
+ if (!name)
+ /* no non-empty line found */
+ return -ENOENT;
+
+ *hostname = name;
+ return 0;
+}
diff --git a/src/shared/hostname-util.h b/src/shared/hostname-util.h
index f2821c3078..0c4763cf5a 100644
--- a/src/shared/hostname-util.h
+++ b/src/shared/hostname-util.h
@@ -35,3 +35,5 @@ char* hostname_cleanup(char *s, bool lowercase);
bool is_localhost(const char *hostname);
int sethostname_idempotent(const char *s);
+
+int read_hostname_config(const char *path, char **hostname);
diff --git a/src/shared/import-util.c b/src/shared/import-util.c
index 660d92ac5d..001a8a37e8 100644
--- a/src/shared/import-util.c
+++ b/src/shared/import-util.c
@@ -150,6 +150,27 @@ int raw_strip_suffixes(const char *p, char **ret) {
return 0;
}
+bool dkr_digest_is_valid(const char *digest) {
+ /* 7 chars for prefix, 64 chars for the digest itself */
+ if (strlen(digest) != 71)
+ return false;
+
+ return startswith(digest, "sha256:") && in_charset(digest + 7, "0123456789abcdef");
+}
+
+bool dkr_ref_is_valid(const char *ref) {
+ const char *colon;
+
+ if (isempty(ref))
+ return false;
+
+ colon = strchr(ref, ':');
+ if (!colon)
+ return filename_is_valid(ref);
+
+ return dkr_digest_is_valid(ref);
+}
+
bool dkr_name_is_valid(const char *name) {
const char *slash, *p;
diff --git a/src/shared/import-util.h b/src/shared/import-util.h
index ff155b0ff2..7bf7d4ca40 100644
--- a/src/shared/import-util.h
+++ b/src/shared/import-util.h
@@ -44,4 +44,6 @@ int raw_strip_suffixes(const char *name, char **ret);
bool dkr_name_is_valid(const char *name);
bool dkr_id_is_valid(const char *id);
+bool dkr_ref_is_valid(const char *ref);
+bool dkr_digest_is_valid(const char *digest);
#define dkr_tag_is_valid(tag) filename_is_valid(tag)
diff --git a/src/shared/json.c b/src/shared/json.c
index 45c8ecedb3..be40a0d203 100644
--- a/src/shared/json.c
+++ b/src/shared/json.c
@@ -21,17 +21,178 @@
#include <sys/types.h>
#include <math.h>
-
#include "macro.h"
-#include "util.h"
#include "utf8.h"
#include "json.h"
-enum {
- STATE_NULL,
- STATE_VALUE,
- STATE_VALUE_POST,
-};
+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;
@@ -285,9 +446,6 @@ static int json_parse_number(const char **p, union json_value *ret) {
} while (strchr("0123456789", *c) && *c != 0);
}
- if (*c != 0)
- return -EINVAL;
-
*p = c;
if (is_double) {
@@ -310,6 +468,12 @@ int json_tokenize(
int t;
int r;
+ enum {
+ STATE_NULL,
+ STATE_VALUE,
+ STATE_VALUE_POST,
+ };
+
assert(p);
assert(*p);
assert(ret_string);
@@ -443,3 +607,260 @@ int json_tokenize(
}
}
+
+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/shared/json.h b/src/shared/json.h
index 55976d513b..e0b4d810b5 100644
--- a/src/shared/json.h
+++ b/src/shared/json.h
@@ -22,6 +22,7 @@
***/
#include <stdbool.h>
+#include "util.h"
enum {
JSON_END,
@@ -38,12 +39,50 @@ enum {
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/shared/log.c b/src/shared/log.c
index 6168a2955d..b96afc4de4 100644
--- a/src/shared/log.c
+++ b/src/shared/log.c
@@ -38,6 +38,7 @@
#include "formats-util.h"
#include "process-util.h"
#include "terminal-util.h"
+#include "signal-util.h"
#define SNDBUF_SIZE (8*1024*1024)
diff --git a/src/shared/machine-pool.c b/src/shared/machine-pool.c
index 9920d150ab..d27931cb4a 100644
--- a/src/shared/machine-pool.c
+++ b/src/shared/machine-pool.c
@@ -30,6 +30,7 @@
#include "mkdir.h"
#include "btrfs-util.h"
#include "path-util.h"
+#include "signal-util.h"
#include "machine-pool.h"
#define VAR_LIB_MACHINES_SIZE_START (1024UL*1024UL*500UL)
@@ -198,7 +199,7 @@ int setup_machine_directory(uint64_t size, sd_bus_error *error) {
return 0;
}
- if (path_is_mount_point("/var/lib/machines", true) > 0 ||
+ if (path_is_mount_point("/var/lib/machines", AT_SYMLINK_FOLLOW) > 0 ||
dir_is_empty("/var/lib/machines") == 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "/var/lib/machines is not a btrfs file system. Operation is not supported on legacy file systems.");
diff --git a/src/shared/missing.h b/src/shared/missing.h
index 8ca6f8edb6..9194009491 100644
--- a/src/shared/missing.h
+++ b/src/shared/missing.h
@@ -713,7 +713,7 @@ static inline int setns(int fd, int nstype) {
#define IFLA_VLAN_MAX (__IFLA_VLAN_MAX - 1)
#endif
-#if !HAVE_DECL_IFLA_VXLAN_LOCAL6
+#if !HAVE_DECL_IFLA_VXLAN_REMCSUM_NOPARTIAL
#define IFLA_VXLAN_UNSPEC 0
#define IFLA_VXLAN_ID 1
#define IFLA_VXLAN_GROUP 2
@@ -732,7 +732,14 @@ static inline int setns(int fd, int nstype) {
#define IFLA_VXLAN_PORT 15
#define IFLA_VXLAN_GROUP6 16
#define IFLA_VXLAN_LOCAL6 17
-#define __IFLA_VXLAN_MAX 18
+#define IFLA_VXLAN_UDP_CSUM 18
+#define IFLA_VXLAN_UDP_ZERO_CSUM6_TX 19
+#define IFLA_VXLAN_UDP_ZERO_CSUM6_RX 20
+#define IFLA_VXLAN_REMCSUM_TX 21
+#define IFLA_VXLAN_REMCSUM_RX 22
+#define IFLA_VXLAN_GBP 23
+#define IFLA_VXLAN_REMCSUM_NOPARTIAL 24
+#define __IFLA_VXLAN_MAX 25
#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)
#endif
diff --git a/src/shared/path-util.c b/src/shared/path-util.c
index 7090989fcb..be50a1865d 100644
--- a/src/shared/path-util.c
+++ b/src/shared/path-util.c
@@ -509,7 +509,7 @@ static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *mnt_id
return safe_atoi(p, mnt_id);
}
-int fd_is_mount_point(int fd) {
+int fd_is_mount_point(int fd, const char *filename, int flags) {
union file_handle_union h = FILE_HANDLE_INIT, h_parent = FILE_HANDLE_INIT;
int mount_id = -1, mount_id_parent = -1;
bool nosupp = false, check_st_dev = true;
@@ -517,6 +517,7 @@ int fd_is_mount_point(int fd) {
int r;
assert(fd >= 0);
+ assert(filename);
/* First we will try the name_to_handle_at() syscall, which
* tells us the mount id and an opaque file "handle". It is
@@ -541,7 +542,7 @@ int fd_is_mount_point(int fd) {
* subvolumes have different st_dev, even though they aren't
* real mounts of their own. */
- r = name_to_handle_at(fd, "", &h.handle, &mount_id, AT_EMPTY_PATH);
+ r = name_to_handle_at(fd, filename, &h.handle, &mount_id, flags);
if (r < 0) {
if (errno == ENOSYS)
/* This kernel does not support name_to_handle_at()
@@ -558,7 +559,7 @@ int fd_is_mount_point(int fd) {
return -errno;
}
- r = name_to_handle_at(fd, "..", &h_parent.handle, &mount_id_parent, 0);
+ r = name_to_handle_at(fd, "", &h_parent.handle, &mount_id_parent, AT_EMPTY_PATH);
if (r < 0) {
if (errno == EOPNOTSUPP) {
if (nosupp)
@@ -593,13 +594,13 @@ int fd_is_mount_point(int fd) {
return mount_id != mount_id_parent;
fallback_fdinfo:
- r = fd_fdinfo_mnt_id(fd, "", AT_EMPTY_PATH, &mount_id);
+ r = fd_fdinfo_mnt_id(fd, filename, flags, &mount_id);
if (r == -EOPNOTSUPP)
goto fallback_fstat;
if (r < 0)
return r;
- r = fd_fdinfo_mnt_id(fd, "..", 0, &mount_id_parent);
+ r = fd_fdinfo_mnt_id(fd, "", AT_EMPTY_PATH, &mount_id_parent);
if (r < 0)
return r;
@@ -615,10 +616,16 @@ fallback_fdinfo:
check_st_dev = false;
fallback_fstat:
- if (fstatat(fd, "", &a, AT_EMPTY_PATH) < 0)
+ /* yay for fstatat() taking a different set of flags than the other
+ * _at() above */
+ if (flags & AT_SYMLINK_FOLLOW)
+ flags &= ~AT_SYMLINK_FOLLOW;
+ else
+ flags |= AT_SYMLINK_NOFOLLOW;
+ if (fstatat(fd, filename, &a, flags) < 0)
return -errno;
- if (fstatat(fd, "..", &b, 0) < 0)
+ if (fstatat(fd, "", &b, AT_EMPTY_PATH) < 0)
return -errno;
/* A directory with same device and inode as its parent? Must
@@ -630,19 +637,26 @@ fallback_fstat:
return check_st_dev && (a.st_dev != b.st_dev);
}
-int path_is_mount_point(const char *t, bool allow_symlink) {
+/* flags can be AT_SYMLINK_FOLLOW or 0 */
+int path_is_mount_point(const char *t, int flags) {
_cleanup_close_ int fd = -1;
+ _cleanup_free_ char *parent = NULL;
+ int r;
assert(t);
if (path_equal(t, "/"))
return 1;
- fd = openat(AT_FDCWD, t, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|(allow_symlink ? 0 : O_PATH));
+ r = path_get_parent(t, &parent);
+ if (r < 0)
+ return r;
+
+ fd = openat(AT_FDCWD, parent, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_PATH);
if (fd < 0)
return -errno;
- return fd_is_mount_point(fd);
+ return fd_is_mount_point(fd, basename(t), flags);
}
int path_is_read_only_fs(const char *path) {
diff --git a/src/shared/path-util.h b/src/shared/path-util.h
index 4f45cfd2b7..1eac89c51b 100644
--- a/src/shared/path-util.h
+++ b/src/shared/path-util.h
@@ -53,8 +53,8 @@ char** path_strv_make_absolute_cwd(char **l);
char** path_strv_resolve(char **l, const char *prefix);
char** path_strv_resolve_uniq(char **l, const char *prefix);
-int fd_is_mount_point(int fd);
-int path_is_mount_point(const char *path, bool allow_symlink);
+int fd_is_mount_point(int fd, const char *filename, int flags);
+int path_is_mount_point(const char *path, int flags);
int path_is_read_only_fs(const char *path);
int path_is_os_tree(const char *path);
diff --git a/src/shared/process-util.c b/src/shared/process-util.c
index 92a69f50e7..cfc876567d 100644
--- a/src/shared/process-util.c
+++ b/src/shared/process-util.c
@@ -28,10 +28,11 @@
#include <signal.h>
#include <ctype.h>
-#include "process-util.h"
#include "fileio.h"
#include "util.h"
#include "log.h"
+#include "signal-util.h"
+#include "process-util.h"
int get_process_state(pid_t pid) {
const char *p;
diff --git a/src/shared/pty.c b/src/shared/pty.c
index 0f80f4863b..119d66e9a2 100644
--- a/src/shared/pty.c
+++ b/src/shared/pty.c
@@ -57,9 +57,10 @@
#include "barrier.h"
#include "macro.h"
-#include "pty.h"
#include "ring.h"
#include "util.h"
+#include "signal-util.h"
+#include "pty.h"
#define PTY_BUFSIZE 4096
diff --git a/src/shared/random-util.c b/src/shared/random-util.c
index 88f5182508..b230044f50 100644
--- a/src/shared/random-util.c
+++ b/src/shared/random-util.c
@@ -23,7 +23,9 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
+#ifdef HAVE_SYS_AUXV_H
#include <sys/auxv.h>
+#endif
#include <linux/random.h>
#include "random-util.h"
diff --git a/src/shared/rm-rf.c b/src/shared/rm-rf.c
index a89e8afc2a..bafd483be2 100644
--- a/src/shared/rm-rf.c
+++ b/src/shared/rm-rf.c
@@ -103,7 +103,7 @@ int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) {
}
/* Stop at mount points */
- r = fd_is_mount_point(subdir_fd);
+ r = fd_is_mount_point(fd, de->d_name, 0);
if (r < 0) {
if (ret == 0 && r != -ENOENT)
ret = r;
diff --git a/src/shared/signal-util.c b/src/shared/signal-util.c
new file mode 100644
index 0000000000..9a2973b6fd
--- /dev/null
+++ b/src/shared/signal-util.c
@@ -0,0 +1,228 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2015 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 "util.h"
+#include "signal-util.h"
+
+int reset_all_signal_handlers(void) {
+ int sig, r = 0;
+
+ for (sig = 1; sig < _NSIG; sig++) {
+ static const struct sigaction sa = {
+ .sa_handler = SIG_DFL,
+ .sa_flags = SA_RESTART,
+ };
+
+ /* These two cannot be caught... */
+ if (sig == SIGKILL || sig == SIGSTOP)
+ continue;
+
+ /* On Linux the first two RT signals are reserved by
+ * glibc, and sigaction() will return EINVAL for them. */
+ if ((sigaction(sig, &sa, NULL) < 0))
+ if (errno != EINVAL && r == 0)
+ r = -errno;
+ }
+
+ return r;
+}
+
+int reset_signal_mask(void) {
+ sigset_t ss;
+
+ if (sigemptyset(&ss) < 0)
+ return -errno;
+
+ if (sigprocmask(SIG_SETMASK, &ss, NULL) < 0)
+ return -errno;
+
+ return 0;
+}
+
+int sigaction_many(const struct sigaction *sa, ...) {
+ va_list ap;
+ int r = 0, sig;
+
+ va_start(ap, sa);
+ while ((sig = va_arg(ap, int)) > 0)
+ if (sigaction(sig, sa, NULL) < 0)
+ r = -errno;
+ va_end(ap);
+
+ return r;
+}
+
+int ignore_signals(int sig, ...) {
+ static const struct sigaction sa = {
+ .sa_handler = SIG_IGN,
+ .sa_flags = SA_RESTART,
+ };
+ va_list ap;
+ int r = 0;
+
+ if (sigaction(sig, &sa, NULL) < 0)
+ r = -errno;
+
+ va_start(ap, sig);
+ while ((sig = va_arg(ap, int)) > 0)
+ if (sigaction(sig, &sa, NULL) < 0)
+ r = -errno;
+ va_end(ap);
+
+ return r;
+}
+
+int default_signals(int sig, ...) {
+ static const struct sigaction sa = {
+ .sa_handler = SIG_DFL,
+ .sa_flags = SA_RESTART,
+ };
+ va_list ap;
+ int r = 0;
+
+ if (sigaction(sig, &sa, NULL) < 0)
+ r = -errno;
+
+ va_start(ap, sig);
+ while ((sig = va_arg(ap, int)) > 0)
+ if (sigaction(sig, &sa, NULL) < 0)
+ r = -errno;
+ va_end(ap);
+
+ return r;
+}
+
+void sigset_add_many(sigset_t *ss, ...) {
+ va_list ap;
+ int sig;
+
+ assert(ss);
+
+ va_start(ap, ss);
+ while ((sig = va_arg(ap, int)) > 0)
+ assert_se(sigaddset(ss, sig) == 0);
+ va_end(ap);
+}
+
+int sigprocmask_many(int how, ...) {
+ va_list ap;
+ sigset_t ss;
+ int sig;
+
+ assert_se(sigemptyset(&ss) == 0);
+
+ va_start(ap, how);
+ while ((sig = va_arg(ap, int)) > 0)
+ assert_se(sigaddset(&ss, sig) == 0);
+ va_end(ap);
+
+ if (sigprocmask(how, &ss, NULL) < 0)
+ return -errno;
+
+ return 0;
+}
+
+static const char *const __signal_table[] = {
+ [SIGHUP] = "HUP",
+ [SIGINT] = "INT",
+ [SIGQUIT] = "QUIT",
+ [SIGILL] = "ILL",
+ [SIGTRAP] = "TRAP",
+ [SIGABRT] = "ABRT",
+ [SIGBUS] = "BUS",
+ [SIGFPE] = "FPE",
+ [SIGKILL] = "KILL",
+ [SIGUSR1] = "USR1",
+ [SIGSEGV] = "SEGV",
+ [SIGUSR2] = "USR2",
+ [SIGPIPE] = "PIPE",
+ [SIGALRM] = "ALRM",
+ [SIGTERM] = "TERM",
+#ifdef SIGSTKFLT
+ [SIGSTKFLT] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */
+#endif
+ [SIGCHLD] = "CHLD",
+ [SIGCONT] = "CONT",
+ [SIGSTOP] = "STOP",
+ [SIGTSTP] = "TSTP",
+ [SIGTTIN] = "TTIN",
+ [SIGTTOU] = "TTOU",
+ [SIGURG] = "URG",
+ [SIGXCPU] = "XCPU",
+ [SIGXFSZ] = "XFSZ",
+ [SIGVTALRM] = "VTALRM",
+ [SIGPROF] = "PROF",
+ [SIGWINCH] = "WINCH",
+ [SIGIO] = "IO",
+ [SIGPWR] = "PWR",
+ [SIGSYS] = "SYS"
+};
+
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
+
+const char *signal_to_string(int signo) {
+ static thread_local char buf[sizeof("RTMIN+")-1 + DECIMAL_STR_MAX(int) + 1];
+ const char *name;
+
+ name = __signal_to_string(signo);
+ if (name)
+ return name;
+
+ if (signo >= SIGRTMIN && signo <= SIGRTMAX)
+ snprintf(buf, sizeof(buf), "RTMIN+%d", signo - SIGRTMIN);
+ else
+ snprintf(buf, sizeof(buf), "%d", signo);
+
+ return buf;
+}
+
+int signal_from_string(const char *s) {
+ int signo;
+ int offset = 0;
+ unsigned u;
+
+ signo = __signal_from_string(s);
+ if (signo > 0)
+ return signo;
+
+ if (startswith(s, "RTMIN+")) {
+ s += 6;
+ offset = SIGRTMIN;
+ }
+ if (safe_atou(s, &u) >= 0) {
+ signo = (int) u + offset;
+ if (signo > 0 && signo < _NSIG)
+ return signo;
+ }
+ return -EINVAL;
+}
+
+int signal_from_string_try_harder(const char *s) {
+ int signo;
+ assert(s);
+
+ signo = signal_from_string(s);
+ if (signo <= 0)
+ if (startswith(s, "SIG"))
+ return signal_from_string(s+3);
+
+ return signo;
+}
diff --git a/src/shared/signal-util.h b/src/shared/signal-util.h
new file mode 100644
index 0000000000..ddf64cda76
--- /dev/null
+++ b/src/shared/signal-util.h
@@ -0,0 +1,41 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010-2015 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 <signal.h>
+
+#include "macro.h"
+
+int reset_all_signal_handlers(void);
+int reset_signal_mask(void);
+
+int ignore_signals(int sig, ...);
+int default_signals(int sig, ...);
+int sigaction_many(const struct sigaction *sa, ...);
+
+void sigset_add_many(sigset_t *ss, ...);
+int sigprocmask_many(int how, ...);
+
+const char *signal_to_string(int i) _const_;
+int signal_from_string(const char *s) _pure_;
+
+int signal_from_string_try_harder(const char *s);
diff --git a/src/shared/switch-root.c b/src/shared/switch-root.c
index ae3839de16..b12189cd10 100644
--- a/src/shared/switch-root.c
+++ b/src/shared/switch-root.c
@@ -105,7 +105,7 @@ int switch_root(const char *new_root, const char *oldroot, bool detach_oldroot,
* to look like. They might even boot, if they are RO and
* don't have the FS layout. Just ignore the error and
* switch_root() nevertheless. */
- (void) base_filesystem_create(new_root);
+ (void) base_filesystem_create(new_root, UID_INVALID, GID_INVALID);
if (chdir(new_root) < 0)
return log_error_errno(errno, "Failed to change directory to %s: %m", new_root);
diff --git a/src/shared/unit-name.c b/src/shared/unit-name.c
index b23e47a2e6..bf52463d81 100644
--- a/src/shared/unit-name.c
+++ b/src/shared/unit-name.c
@@ -812,6 +812,8 @@ static const char* const unit_dependency_table[_UNIT_DEPENDENCY_MAX] = {
[UNIT_PART_OF] = "PartOf",
[UNIT_REQUIRED_BY] = "RequiredBy",
[UNIT_REQUIRED_BY_OVERRIDABLE] = "RequiredByOverridable",
+ [UNIT_REQUISITE_OF] = "RequisiteOf",
+ [UNIT_REQUISITE_OF_OVERRIDABLE] = "RequisiteOfOverridable",
[UNIT_WANTED_BY] = "WantedBy",
[UNIT_BOUND_BY] = "BoundBy",
[UNIT_CONSISTS_OF] = "ConsistsOf",
diff --git a/src/shared/unit-name.h b/src/shared/unit-name.h
index c2f31e3f90..b2043d0870 100644
--- a/src/shared/unit-name.h
+++ b/src/shared/unit-name.h
@@ -71,8 +71,10 @@ enum UnitDependency {
UNIT_PART_OF,
/* Inverse of the above */
- UNIT_REQUIRED_BY, /* inverse of 'requires' and 'requisite' is 'required_by' */
- UNIT_REQUIRED_BY_OVERRIDABLE, /* inverse of 'requires_overridable' and 'requisite_overridable' is 'soft_required_by' */
+ UNIT_REQUIRED_BY, /* inverse of 'requires' is 'required_by' */
+ UNIT_REQUIRED_BY_OVERRIDABLE, /* inverse of 'requires_overridable' is 'required_by_overridable' */
+ UNIT_REQUISITE_OF, /* inverse of 'requisite' is 'requisite_of' */
+ UNIT_REQUISITE_OF_OVERRIDABLE,/* inverse of 'requisite_overridable' is 'requisite_of_overridable' */
UNIT_WANTED_BY, /* inverse of 'wants' */
UNIT_BOUND_BY, /* inverse of 'binds_to' */
UNIT_CONSISTS_OF, /* inverse of 'part_of' */
diff --git a/src/shared/util.c b/src/shared/util.c
index da6343f4c4..8a6107969a 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -93,6 +93,7 @@
#include "random-util.h"
#include "terminal-util.h"
#include "hostname-util.h"
+#include "signal-util.h"
/* Put this test here for a lack of better place */
assert_cc(EAGAIN == EWOULDBLOCK);
@@ -148,6 +149,27 @@ char* endswith(const char *s, const char *postfix) {
return (char*) s + sl - pl;
}
+char* endswith_no_case(const char *s, const char *postfix) {
+ size_t sl, pl;
+
+ assert(s);
+ assert(postfix);
+
+ sl = strlen(s);
+ pl = strlen(postfix);
+
+ if (pl == 0)
+ return (char*) s + sl;
+
+ if (sl < pl)
+ return NULL;
+
+ if (strcasecmp(s + sl - pl, postfix) != 0)
+ return NULL;
+
+ return (char*) s + sl - pl;
+}
+
char* first_word(const char *s, const char *word) {
size_t sl, wl;
const char *p;
@@ -750,41 +772,6 @@ int readlink_and_canonicalize(const char *p, char **r) {
return 0;
}
-int reset_all_signal_handlers(void) {
- int sig, r = 0;
-
- for (sig = 1; sig < _NSIG; sig++) {
- struct sigaction sa = {
- .sa_handler = SIG_DFL,
- .sa_flags = SA_RESTART,
- };
-
- /* These two cannot be caught... */
- if (sig == SIGKILL || sig == SIGSTOP)
- continue;
-
- /* On Linux the first two RT signals are reserved by
- * glibc, and sigaction() will return EINVAL for them. */
- if ((sigaction(sig, &sa, NULL) < 0))
- if (errno != EINVAL && r == 0)
- r = -errno;
- }
-
- return r;
-}
-
-int reset_signal_mask(void) {
- sigset_t ss;
-
- if (sigemptyset(&ss) < 0)
- return -errno;
-
- if (sigprocmask(SIG_SETMASK, &ss, NULL) < 0)
- return -errno;
-
- return 0;
-}
-
char *strstrip(char *s) {
char *e;
@@ -1540,59 +1527,6 @@ int flush_fd(int fd) {
}
}
-int sigaction_many(const struct sigaction *sa, ...) {
- va_list ap;
- int r = 0, sig;
-
- va_start(ap, sa);
- while ((sig = va_arg(ap, int)) > 0)
- if (sigaction(sig, sa, NULL) < 0)
- r = -errno;
- va_end(ap);
-
- return r;
-}
-
-int ignore_signals(int sig, ...) {
- struct sigaction sa = {
- .sa_handler = SIG_IGN,
- .sa_flags = SA_RESTART,
- };
- va_list ap;
- int r = 0;
-
- if (sigaction(sig, &sa, NULL) < 0)
- r = -errno;
-
- va_start(ap, sig);
- while ((sig = va_arg(ap, int)) > 0)
- if (sigaction(sig, &sa, NULL) < 0)
- r = -errno;
- va_end(ap);
-
- return r;
-}
-
-int default_signals(int sig, ...) {
- struct sigaction sa = {
- .sa_handler = SIG_DFL,
- .sa_flags = SA_RESTART,
- };
- va_list ap;
- int r = 0;
-
- if (sigaction(sig, &sa, NULL) < 0)
- r = -errno;
-
- va_start(ap, sig);
- while ((sig = va_arg(ap, int)) > 0)
- if (sigaction(sig, &sa, NULL) < 0)
- r = -errno;
- va_end(ap);
-
- return r;
-}
-
void safe_close_pair(int p[]) {
assert(p);
@@ -1697,7 +1631,7 @@ int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
int parse_size(const char *t, off_t base, off_t *size) {
- /* Soo, sometimes we want to parse IEC binary suffxies, and
+ /* Soo, sometimes we want to parse IEC binary suffixes, and
* sometimes SI decimal suffixes. This function can parse
* both. Which one is the right way depends on the
* context. Wikipedia suggests that SI is customary for
@@ -1906,35 +1840,6 @@ void rename_process(const char name[8]) {
}
}
-void sigset_add_many(sigset_t *ss, ...) {
- va_list ap;
- int sig;
-
- assert(ss);
-
- va_start(ap, ss);
- while ((sig = va_arg(ap, int)) > 0)
- assert_se(sigaddset(ss, sig) == 0);
- va_end(ap);
-}
-
-int sigprocmask_many(int how, ...) {
- va_list ap;
- sigset_t ss;
- int sig;
-
- assert_se(sigemptyset(&ss) == 0);
-
- va_start(ap, how);
- while ((sig = va_arg(ap, int)) > 0)
- assert_se(sigaddset(&ss, sig) == 0);
- va_end(ap);
-
- if (sigprocmask(how, &ss, NULL) < 0)
- return -errno;
-
- return 0;
-}
char *lookup_uid(uid_t uid) {
long bufsize;
char *name;
@@ -2323,18 +2228,6 @@ DIR *xopendirat(int fd, const char *name, int flags) {
return d;
}
-int signal_from_string_try_harder(const char *s) {
- int signo;
- assert(s);
-
- signo = signal_from_string(s);
- if (signo <= 0)
- if (startswith(s, "SIG"))
- return signal_from_string(s+3);
-
- return signo;
-}
-
static char *tag_to_udev_node(const char *tagvalue, const char *by) {
_cleanup_free_ char *t = NULL, *u = NULL;
size_t enc_len;
@@ -3291,81 +3184,6 @@ static const char* const ip_tos_table[] = {
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
-static const char *const __signal_table[] = {
- [SIGHUP] = "HUP",
- [SIGINT] = "INT",
- [SIGQUIT] = "QUIT",
- [SIGILL] = "ILL",
- [SIGTRAP] = "TRAP",
- [SIGABRT] = "ABRT",
- [SIGBUS] = "BUS",
- [SIGFPE] = "FPE",
- [SIGKILL] = "KILL",
- [SIGUSR1] = "USR1",
- [SIGSEGV] = "SEGV",
- [SIGUSR2] = "USR2",
- [SIGPIPE] = "PIPE",
- [SIGALRM] = "ALRM",
- [SIGTERM] = "TERM",
-#ifdef SIGSTKFLT
- [SIGSTKFLT] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */
-#endif
- [SIGCHLD] = "CHLD",
- [SIGCONT] = "CONT",
- [SIGSTOP] = "STOP",
- [SIGTSTP] = "TSTP",
- [SIGTTIN] = "TTIN",
- [SIGTTOU] = "TTOU",
- [SIGURG] = "URG",
- [SIGXCPU] = "XCPU",
- [SIGXFSZ] = "XFSZ",
- [SIGVTALRM] = "VTALRM",
- [SIGPROF] = "PROF",
- [SIGWINCH] = "WINCH",
- [SIGIO] = "IO",
- [SIGPWR] = "PWR",
- [SIGSYS] = "SYS"
-};
-
-DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
-
-const char *signal_to_string(int signo) {
- static thread_local char buf[sizeof("RTMIN+")-1 + DECIMAL_STR_MAX(int) + 1];
- const char *name;
-
- name = __signal_to_string(signo);
- if (name)
- return name;
-
- if (signo >= SIGRTMIN && signo <= SIGRTMAX)
- snprintf(buf, sizeof(buf), "RTMIN+%d", signo - SIGRTMIN);
- else
- snprintf(buf, sizeof(buf), "%d", signo);
-
- return buf;
-}
-
-int signal_from_string(const char *s) {
- int signo;
- int offset = 0;
- unsigned u;
-
- signo = __signal_from_string(s);
- if (signo > 0)
- return signo;
-
- if (startswith(s, "RTMIN+")) {
- s += 6;
- offset = SIGRTMIN;
- }
- if (safe_atou(s, &u) >= 0) {
- signo = (int) u + offset;
- if (signo > 0 && signo < _NSIG)
- return signo;
- }
- return -EINVAL;
-}
-
bool kexec_loaded(void) {
bool loaded = false;
char *s;
@@ -4665,16 +4483,7 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int root_fd) {
return -errno;
}
- if (setresgid(0, 0, 0) < 0)
- return -errno;
-
- if (setgroups(0, NULL) < 0)
- return -errno;
-
- if (setresuid(0, 0, 0) < 0)
- return -errno;
-
- return 0;
+ return reset_uid_gid();
}
int getpeercred(int fd, struct ucred *ucred) {
@@ -4825,10 +4634,7 @@ unsigned long personality_from_string(const char *p) {
return PER_LINUX;
#endif
- /* personality(7) documents that 0xffffffffUL is used for
- * querying the current personality, hence let's use that here
- * as error indicator. */
- return 0xffffffffUL;
+ return PERSONALITY_INVALID;
}
const char* personality_to_string(unsigned long p) {
@@ -5878,7 +5684,7 @@ int same_fd(int a, int b) {
/* The fds refer to the same inode on disk, let's also check
* if they have the same fd flags. This is useful to
- * distuingish the read and write side of a pipe created with
+ * distinguish the read and write side of a pipe created with
* pipe(). */
fa = fcntl(a, F_GETFL);
if (fa < 0)
@@ -6208,3 +6014,35 @@ int parse_mode(const char *s, mode_t *ret) {
*ret = (mode_t) l;
return 0;
}
+
+int mount_move_root(const char *path) {
+ assert(path);
+
+ if (chdir(path) < 0)
+ return -errno;
+
+ if (mount(path, "/", NULL, MS_MOVE, NULL) < 0)
+ return -errno;
+
+ if (chroot(".") < 0)
+ return -errno;
+
+ if (chdir("/") < 0)
+ return -errno;
+
+ return 0;
+}
+
+int reset_uid_gid(void) {
+
+ if (setgroups(0, NULL) < 0)
+ return -errno;
+
+ if (setresgid(0, 0, 0) < 0)
+ return -errno;
+
+ if (setresuid(0, 0, 0) < 0)
+ return -errno;
+
+ return 0;
+}
diff --git a/src/shared/util.h b/src/shared/util.h
index a2b1ec5030..467ae234a0 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -29,7 +29,6 @@
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
-#include <signal.h>
#include <sched.h>
#include <limits.h>
#include <sys/types.h>
@@ -134,6 +133,7 @@ static inline char *startswith_no_case(const char *s, const char *prefix) {
}
char *endswith(const char *s, const char *postfix) _pure_;
+char *endswith_no_case(const char *s, const char *postfix) _pure_;
char *first_word(const char *s, const char *word) _pure_;
@@ -226,9 +226,6 @@ int readlink_value(const char *p, char **ret);
int readlink_and_make_absolute(const char *p, char **r);
int readlink_and_canonicalize(const char *p, char **r);
-int reset_all_signal_handlers(void);
-int reset_signal_mask(void);
-
char *strstrip(char *s);
char *delete_chars(char *s, const char *bad);
char *truncate_nl(char *s);
@@ -333,10 +330,6 @@ bool fstype_is_network(const char *fstype);
int flush_fd(int fd);
-int ignore_signals(int sig, ...);
-int default_signals(int sig, ...);
-int sigaction_many(const struct sigaction *sa, ...);
-
int fopen_temporary(const char *path, FILE **_f, char **_temp_path);
ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll);
@@ -348,9 +341,6 @@ bool is_device_path(const char *path);
int dir_is_empty(const char *path);
char* dirname_malloc(const char *path);
-void sigset_add_many(sigset_t *ss, ...);
-int sigprocmask_many(int how, ...);
-
char* lookup_uid(uid_t uid);
char* getlogname_malloc(void);
char* getusername_malloc(void);
@@ -464,11 +454,6 @@ int rlimit_from_string(const char *s) _pure_;
int ip_tos_to_string_alloc(int i, char **s);
int ip_tos_from_string(const char *s);
-const char *signal_to_string(int i) _const_;
-int signal_from_string(const char *s) _pure_;
-
-int signal_from_string_try_harder(const char *s);
-
extern int saved_argc;
extern char **saved_argv;
@@ -774,7 +759,7 @@ int shall_restore_state(void);
* that only if nmemb > 0.
*/
static inline void qsort_safe(void *base, size_t nmemb, size_t size, comparison_fn_t compar) {
- if (nmemb <= 0)
+ if (nmemb <= 1)
return;
assert(base);
@@ -815,6 +800,13 @@ int open_tmpfile(const char *path, int flags);
int fd_warn_permissions(const char *path, int fd);
+#ifndef PERSONALITY_INVALID
+/* personality(7) documents that 0xffffffffUL is used for querying the
+ * current personality, hence let's use that here as error
+ * indicator. */
+#define PERSONALITY_INVALID 0xffffffffLU
+#endif
+
unsigned long personality_from_string(const char *p);
const char *personality_to_string(unsigned long);
@@ -905,3 +897,7 @@ int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char
char *shell_maybe_quote(const char *s);
int parse_mode(const char *s, mode_t *ret);
+
+int mount_move_root(const char *path);
+
+int reset_uid_gid(void);