summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/systemd/src/basic/alloc-util.h15
-rw-r--r--src/systemd/src/basic/env-util.c157
-rw-r--r--src/systemd/src/basic/env-util.h3
-rw-r--r--src/systemd/src/basic/fd-util.c24
-rw-r--r--src/systemd/src/basic/fileio.c18
-rw-r--r--src/systemd/src/basic/fileio.h10
-rw-r--r--src/systemd/src/basic/fs-util.c32
-rw-r--r--src/systemd/src/basic/fs-util.h1
-rw-r--r--src/systemd/src/basic/hashmap.c63
-rw-r--r--src/systemd/src/basic/hashmap.h51
-rw-r--r--src/systemd/src/basic/list.h6
-rw-r--r--src/systemd/src/basic/macro.h25
-rw-r--r--src/systemd/src/basic/mempool.c18
-rw-r--r--src/systemd/src/basic/mempool.h4
-rw-r--r--src/systemd/src/basic/path-util.c40
-rw-r--r--src/systemd/src/basic/path-util.h1
-rw-r--r--src/systemd/src/basic/prioq.c13
-rw-r--r--src/systemd/src/basic/prioq.h1
-rw-r--r--src/systemd/src/basic/process-util.c46
-rw-r--r--src/systemd/src/basic/process-util.h9
-rw-r--r--src/systemd/src/basic/set.h4
-rw-r--r--src/systemd/src/basic/siphash24.h5
-rw-r--r--src/systemd/src/basic/socket-util.c146
-rw-r--r--src/systemd/src/basic/socket-util.h18
-rw-r--r--src/systemd/src/basic/string-util.c28
-rw-r--r--src/systemd/src/basic/string-util.h26
-rw-r--r--src/systemd/src/basic/strv.c9
-rw-r--r--src/systemd/src/basic/strv.h6
-rw-r--r--src/systemd/src/basic/time-util.c124
-rw-r--r--src/systemd/src/basic/time-util.h4
-rw-r--r--src/systemd/src/basic/util.c15
-rw-r--r--src/systemd/src/basic/util.h8
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-network.c28
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-internal.h4
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-network.c14
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-option.c168
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp-client.c4
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp6-client.c26
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp6-lease.c11
-rw-r--r--src/systemd/src/libsystemd/sd-event/sd-event.c66
-rw-r--r--src/systemd/src/systemd/sd-event.h3
41 files changed, 677 insertions, 577 deletions
diff --git a/src/systemd/src/basic/alloc-util.h b/src/systemd/src/basic/alloc-util.h
index ebe42889ea..2a6deb12ca 100644
--- a/src/systemd/src/basic/alloc-util.h
+++ b/src/systemd/src/basic/alloc-util.h
@@ -46,6 +46,21 @@ static inline void *mfree(void *memory) {
void* memdup(const void *p, size_t l) _alloc_(2);
void* memdup_suffix0(const void *p, size_t l) _alloc_(2);
+#define memdupa(p, l) \
+ ({ \
+ void *_q_; \
+ _q_ = alloca(l); \
+ memcpy(_q_, p, l); \
+ })
+
+#define memdupa_suffix0(p, l) \
+ ({ \
+ void *_q_; \
+ _q_ = alloca(l + 1); \
+ ((uint8_t*) _q_)[l] = 0; \
+ memcpy(_q_, p, l); \
+ })
+
static inline void freep(void *p) {
free(*(void**) p);
}
diff --git a/src/systemd/src/basic/env-util.c b/src/systemd/src/basic/env-util.c
index 3b8130b03e..e494f65c98 100644
--- a/src/systemd/src/basic/env-util.c
+++ b/src/systemd/src/basic/env-util.c
@@ -21,10 +21,6 @@
DIGITS LETTERS \
"_"
-#ifndef ARG_MAX
-#define ARG_MAX ((size_t) sysconf(_SC_ARG_MAX))
-#endif
-
static bool env_name_is_valid_n(const char *e, size_t n) {
const char *p;
@@ -42,7 +38,7 @@ static bool env_name_is_valid_n(const char *e, size_t n) {
* either. Discounting the equal sign and trailing NUL this
* hence leaves ARG_MAX-2 as longest possible variable
* name. */
- if (n > ARG_MAX - 2)
+ if (n > (size_t) sysconf(_SC_ARG_MAX) - 2)
return false;
for (p = e; p < e + n; p++)
@@ -76,7 +72,7 @@ bool env_value_is_valid(const char *e) {
* either. Discounting the shortest possible variable name of
* length 1, the equal sign and trailing NUL this hence leaves
* ARG_MAX-3 as longest possible variable value. */
- if (strlen(e) > ARG_MAX - 3)
+ if (strlen(e) > (size_t) sysconf(_SC_ARG_MAX) - 3)
return false;
return true;
@@ -99,7 +95,7 @@ bool env_assignment_is_valid(const char *e) {
* be > ARG_MAX, hence the individual variable assignments
* cannot be either, but let's leave room for one trailing NUL
* byte. */
- if (strlen(e) > ARG_MAX - 1)
+ if (strlen(e) > (size_t) sysconf(_SC_ARG_MAX) - 1)
return false;
return true;
@@ -125,30 +121,28 @@ bool strv_env_is_valid(char **e) {
}
bool strv_env_name_is_valid(char **l) {
- char **p, **q;
+ char **p;
STRV_FOREACH(p, l) {
if (!env_name_is_valid(*p))
return false;
- STRV_FOREACH(q, p + 1)
- if (streq(*p, *q))
- return false;
+ if (strv_contains(p + 1, *p))
+ return false;
}
return true;
}
bool strv_env_name_or_assignment_is_valid(char **l) {
- char **p, **q;
+ char **p;
STRV_FOREACH(p, l) {
if (!env_assignment_is_valid(*p) && !env_name_is_valid(*p))
return false;
- STRV_FOREACH(q, p + 1)
- if (streq(*p, *q))
- return false;
+ if (strv_contains(p + 1, *p))
+ return false;
}
return true;
@@ -157,20 +151,23 @@ bool strv_env_name_or_assignment_is_valid(char **l) {
static int env_append(char **r, char ***k, char **a) {
assert(r);
assert(k);
+ assert(*k >= r);
if (!a)
return 0;
- /* Add the entries of a to *k unless they already exist in *r
- * in which case they are overridden instead. This assumes
- * there is enough space in the r array. */
+ /* Expects the following arguments: 'r' shall point to the beginning of an strv we are going to append to, 'k'
+ * to a pointer pointing to the NULL entry at the end of the same array. 'a' shall point to another strv.
+ *
+ * This call adds every entry of 'a' to 'r', either overriding an existing matching entry, or appending to it.
+ *
+ * This call assumes 'r' has enough pre-allocated space to grow by all of 'a''s items. */
for (; *a; a++) {
- char **j;
+ char **j, *c;
size_t n;
n = strcspn(*a, "=");
-
if ((*a)[n] == '=')
n++;
@@ -178,24 +175,26 @@ static int env_append(char **r, char ***k, char **a) {
if (strneq(*j, *a, n))
break;
- if (j >= *k)
- (*k)++;
- else
- free(*j);
-
- *j = strdup(*a);
- if (!*j)
+ c = strdup(*a);
+ if (!c)
return -ENOMEM;
+
+ if (j >= *k) { /* Append to the end? */
+ (*k)[0] = c;
+ (*k)[1] = NULL;
+ (*k)++;
+ } else
+ free_and_replace(*j, c); /* Override existing item */
}
return 0;
}
char **strv_env_merge(size_t n_lists, ...) {
- size_t n = 0;
- char **l, **k, **r;
+ _cleanup_strv_free_ char **ret = NULL;
+ size_t n = 0, i;
+ char **l, **k;
va_list ap;
- size_t i;
/* Merges an arbitrary number of environment sets */
@@ -206,29 +205,24 @@ char **strv_env_merge(size_t n_lists, ...) {
}
va_end(ap);
- r = new(char*, n+1);
- if (!r)
+ ret = new(char*, n+1);
+ if (!ret)
return NULL;
- k = r;
+ *ret = NULL;
+ k = ret;
va_start(ap, n_lists);
for (i = 0; i < n_lists; i++) {
l = va_arg(ap, char**);
- if (env_append(r, &k, l) < 0)
- goto fail;
+ if (env_append(ret, &k, l) < 0) {
+ va_end(ap);
+ return NULL;
+ }
}
va_end(ap);
- *k = NULL;
-
- return r;
-
-fail:
- va_end(ap);
- strv_free(r);
-
- return NULL;
+ return TAKE_PTR(ret);
}
static bool env_match(const char *t, const char *pattern) {
@@ -382,22 +376,23 @@ char **strv_env_unset_many(char **l, ...) {
}
int strv_env_replace(char ***l, char *p) {
- char **f;
const char *t, *name;
+ char **f;
+ int r;
assert(p);
- /* Replace first occurrence of the env var or add a new one in the
- * string list. Drop other occurrences. Edits in-place. Does not copy p.
- * p must be a valid key=value assignment.
+ /* Replace first occurrence of the env var or add a new one in the string list. Drop other occurrences. Edits
+ * in-place. Does not copy p. p must be a valid key=value assignment.
*/
t = strchr(p, '=');
- assert(t);
+ if (!t)
+ return -EINVAL;
name = strndupa(p, t - p);
- for (f = *l; f && *f; f++)
+ STRV_FOREACH(f, *l)
if (env_entry_has_name(*f, name)) {
free_and_replace(*f, p);
strv_env_unset(f + 1, *f);
@@ -405,33 +400,40 @@ int strv_env_replace(char ***l, char *p) {
}
/* We didn't find a match, we need to append p or create a new strv */
- if (strv_push(l, p) < 0)
- return -ENOMEM;
+ r = strv_push(l, p);
+ if (r < 0)
+ return r;
+
return 1;
}
char **strv_env_set(char **x, const char *p) {
+ _cleanup_strv_free_ char **ret = NULL;
+ size_t n, m;
char **k;
- _cleanup_strv_free_ char **r = NULL;
- char* m[2] = { (char*) p, NULL };
/* Overrides the env var setting of p, returns a new copy */
- r = new(char*, strv_length(x)+2);
- if (!r)
+ n = strv_length(x);
+ m = n + 2;
+ if (m < n) /* overflow? */
return NULL;
- k = r;
- if (env_append(r, &k, x) < 0)
+ ret = new(char*, m);
+ if (!ret)
return NULL;
- if (env_append(r, &k, m) < 0)
+ *ret = NULL;
+ k = ret;
+
+ if (env_append(ret, &k, x) < 0)
return NULL;
- *k = NULL;
+ if (env_append(ret, &k, STRV_MAKE(p)) < 0)
+ return NULL;
- return TAKE_PTR(r);
+ return TAKE_PTR(ret);
}
char *strv_env_get_n(char **l, const char *name, size_t k, unsigned flags) {
@@ -750,36 +752,3 @@ int getenv_bool_secure(const char *p) {
return parse_boolean(e);
}
-
-int serialize_environment(FILE *f, char **environment) {
- char **e;
-
- STRV_FOREACH(e, environment) {
- _cleanup_free_ char *ce;
-
- ce = cescape(*e);
- if (!ce)
- return -ENOMEM;
-
- fprintf(f, "env=%s\n", ce);
- }
-
- /* caller should call ferror() */
-
- return 0;
-}
-
-int deserialize_environment(char ***environment, const char *line) {
- char *uce;
- int r;
-
- assert(line);
- assert(environment);
-
- assert(startswith(line, "env="));
- r = cunescape(line + 4, 0, &uce);
- if (r < 0)
- return r;
-
- return strv_env_replace(environment, uce);
-}
diff --git a/src/systemd/src/basic/env-util.h b/src/systemd/src/basic/env-util.h
index 174433ea91..4d21ea6bef 100644
--- a/src/systemd/src/basic/env-util.h
+++ b/src/systemd/src/basic/env-util.h
@@ -45,6 +45,3 @@ char *strv_env_get(char **x, const char *n) _pure_;
int getenv_bool(const char *p);
int getenv_bool_secure(const char *p);
-
-int serialize_environment(FILE *f, char **environment);
-int deserialize_environment(char ***environment, const char *line);
diff --git a/src/systemd/src/basic/fd-util.c b/src/systemd/src/basic/fd-util.c
index b97bd191ab..5775a13e3e 100644
--- a/src/systemd/src/basic/fd-util.c
+++ b/src/systemd/src/basic/fd-util.c
@@ -353,22 +353,22 @@ bool fdname_is_valid(const char *s) {
}
int fd_get_path(int fd, char **ret) {
- _cleanup_close_ int dir = -1;
- char fdname[DECIMAL_STR_MAX(int)];
+ char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
int r;
- dir = open("/proc/self/fd/", O_CLOEXEC | O_DIRECTORY | O_PATH);
- if (dir < 0)
- /* /proc is not available or not set up properly, we're most likely
- * in some chroot environment. */
- return errno == ENOENT ? -EOPNOTSUPP : -errno;
+ xsprintf(procfs_path, "/proc/self/fd/%i", fd);
+ r = readlink_malloc(procfs_path, ret);
+ if (r == -ENOENT) {
+ /* ENOENT can mean two things: that the fd does not exist or that /proc is not mounted. Let's make
+ * things debuggable and distuingish the two. */
- xsprintf(fdname, "%i", fd);
+ if (access("/proc/self/fd/", F_OK) < 0)
+ /* /proc is not available or not set up properly, we're most likely in some chroot
+ * environment. */
+ return errno == ENOENT ? -EOPNOTSUPP : -errno;
- r = readlinkat_malloc(dir, fdname, ret);
- if (r == -ENOENT)
- /* If the file doesn't exist the fd is invalid */
- return -EBADF;
+ return -EBADF; /* The directory exists, hence it's the fd that doesn't. */
+ }
return r;
}
diff --git a/src/systemd/src/basic/fileio.c b/src/systemd/src/basic/fileio.c
index d2fd4c47b3..f14afa5dce 100644
--- a/src/systemd/src/basic/fileio.c
+++ b/src/systemd/src/basic/fileio.c
@@ -1221,6 +1221,24 @@ int mkostemp_safe(char *pattern) {
return fd;
}
+int fmkostemp_safe(char *pattern, const char *mode, FILE **ret_f) {
+ int fd;
+ FILE *f;
+
+ fd = mkostemp_safe(pattern);
+ if (fd < 0)
+ return fd;
+
+ f = fdopen(fd, mode);
+ if (!f) {
+ safe_close(fd);
+ return -errno;
+ }
+
+ *ret_f = f;
+ return 0;
+}
+
int tempfn_xxxxxx(const char *p, const char *extra, char **ret) {
const char *fn;
char *t;
diff --git a/src/systemd/src/basic/fileio.h b/src/systemd/src/basic/fileio.h
index 77e6206e95..102d33d75f 100644
--- a/src/systemd/src/basic/fileio.h
+++ b/src/systemd/src/basic/fileio.h
@@ -59,20 +59,12 @@ DIR *xopendirat(int dirfd, const char *name, int flags);
int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f);
int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f);
-#define FOREACH_LINE(line, f, on_error) \
- for (;;) \
- if (!fgets(line, sizeof(line), f)) { \
- if (ferror(f)) { \
- on_error; \
- } \
- break; \
- } else
-
int fflush_and_check(FILE *f);
int fflush_sync_and_check(FILE *f);
int fopen_temporary(const char *path, FILE **_f, char **_temp_path);
int mkostemp_safe(char *pattern);
+int fmkostemp_safe(char *pattern, const char *mode, FILE**_f);
int tempfn_xxxxxx(const char *p, const char *extra, char **ret);
int tempfn_random(const char *p, const char *extra, char **ret);
diff --git a/src/systemd/src/basic/fs-util.c b/src/systemd/src/basic/fs-util.c
index 3d83fc9b10..55651baa80 100644
--- a/src/systemd/src/basic/fs-util.c
+++ b/src/systemd/src/basic/fs-util.c
@@ -132,7 +132,7 @@ int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char
}
int readlinkat_malloc(int fd, const char *p, char **ret) {
- size_t l = 100;
+ size_t l = FILENAME_MAX+1;
int r;
assert(p);
@@ -1173,7 +1173,7 @@ int unlinkat_deallocate(int fd, const char *name, int flags) {
return 0;
if (fstat(truncate_fd, &st) < 0) {
- log_debug_errno(errno, "Failed to stat file '%s' for deallocation, ignoring.", name);
+ log_debug_errno(errno, "Failed to stat file '%s' for deallocation, ignoring: %m", name);
return 0;
}
@@ -1235,6 +1235,34 @@ int fsync_directory_of_file(int fd) {
return 0;
}
+int fsync_path_at(int at_fd, const char *path) {
+ _cleanup_close_ int opened_fd = -1;
+ int fd;
+
+ if (isempty(path)) {
+ if (at_fd == AT_FDCWD) {
+ opened_fd = open(".", O_RDONLY|O_DIRECTORY|O_CLOEXEC);
+ if (opened_fd < 0)
+ return -errno;
+
+ fd = opened_fd;
+ } else
+ fd = at_fd;
+ } else {
+
+ opened_fd = openat(at_fd, path, O_RDONLY|O_CLOEXEC);
+ if (opened_fd < 0)
+ return -errno;
+
+ fd = opened_fd;
+ }
+
+ if (fsync(fd) < 0)
+ return -errno;
+
+ return 0;
+}
+
int open_parent(const char *path, int flags, mode_t mode) {
_cleanup_free_ char *parent = NULL;
int fd;
diff --git a/src/systemd/src/basic/fs-util.h b/src/systemd/src/basic/fs-util.h
index bc753d5920..955b146a6a 100644
--- a/src/systemd/src/basic/fs-util.h
+++ b/src/systemd/src/basic/fs-util.h
@@ -105,5 +105,6 @@ void unlink_tempfilep(char (*p)[]);
int unlinkat_deallocate(int fd, const char *name, int flags);
int fsync_directory_of_file(int fd);
+int fsync_path_at(int at_fd, const char *path);
int open_parent(const char *path, int flags, mode_t mode);
diff --git a/src/systemd/src/basic/hashmap.c b/src/systemd/src/basic/hashmap.c
index 44d718c83d..eba56add1f 100644
--- a/src/systemd/src/basic/hashmap.c
+++ b/src/systemd/src/basic/hashmap.c
@@ -6,7 +6,6 @@
#include <string.h>
#include "alloc-util.h"
-#include "env-util.h"
#include "fileio.h"
#include "hashmap.h"
#include "macro.h"
@@ -767,24 +766,12 @@ static void reset_direct_storage(HashmapBase *h) {
memset(p, DIB_RAW_INIT, sizeof(dib_raw_t) * hi->n_direct_buckets);
}
-static bool use_pool(void) {
- static int b = -1;
-
- if (!is_main_thread())
- return false;
-
- if (b < 0)
- b = getenv_bool("SYSTEMD_MEMPOOL") != 0;
-
- return b;
-}
-
static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enum HashmapType type HASHMAP_DEBUG_PARAMS) {
HashmapBase *h;
const struct hashmap_type_info *hi = &hashmap_type_info[type];
bool up;
- up = use_pool();
+ up = mempool_enabled();
h = up ? mempool_alloc0_tile(hi->mempool) : malloc0(hi->head_size);
if (!h)
@@ -1556,18 +1543,9 @@ static unsigned find_first_entry(HashmapBase *h) {
return hashmap_iterate_entry(h, &i);
}
-void *internal_hashmap_first(HashmapBase *h) {
- unsigned idx;
-
- idx = find_first_entry(h);
- if (idx == IDX_NIL)
- return NULL;
-
- return entry_value(h, bucket_at(h, idx));
-}
-
-void *internal_hashmap_first_key(HashmapBase *h) {
+void *internal_hashmap_first_key_and_value(HashmapBase *h, bool remove, void **ret_key) {
struct hashmap_base_entry *e;
+ void *key, *data;
unsigned idx;
idx = find_first_entry(h);
@@ -1575,39 +1553,16 @@ void *internal_hashmap_first_key(HashmapBase *h) {
return NULL;
e = bucket_at(h, idx);
- return (void*) e->key;
-}
-
-void *internal_hashmap_steal_first(HashmapBase *h) {
- struct hashmap_base_entry *e;
- void *data;
- unsigned idx;
-
- idx = find_first_entry(h);
- if (idx == IDX_NIL)
- return NULL;
-
- e = bucket_at(h, idx);
+ key = (void*) e->key;
data = entry_value(h, e);
- remove_entry(h, idx);
-
- return data;
-}
-void *internal_hashmap_steal_first_key(HashmapBase *h) {
- struct hashmap_base_entry *e;
- void *key;
- unsigned idx;
-
- idx = find_first_entry(h);
- if (idx == IDX_NIL)
- return NULL;
+ if (remove)
+ remove_entry(h, idx);
- e = bucket_at(h, idx);
- key = (void*) e->key;
- remove_entry(h, idx);
+ if (ret_key)
+ *ret_key = key;
- return key;
+ return data;
}
unsigned internal_hashmap_size(HashmapBase *h) {
diff --git a/src/systemd/src/basic/hashmap.h b/src/systemd/src/basic/hashmap.h
index b771ceccdc..bb2a5c76ec 100644
--- a/src/systemd/src/basic/hashmap.h
+++ b/src/systemd/src/basic/hashmap.h
@@ -290,36 +290,51 @@ static inline void ordered_hashmap_clear_free_free(OrderedHashmap *h) {
* the first entry is O(1).
*/
-void *internal_hashmap_steal_first(HashmapBase *h);
+void *internal_hashmap_first_key_and_value(HashmapBase *h, bool remove, void **ret_key);
+static inline void *hashmap_steal_first_key_and_value(Hashmap *h, void **ret) {
+ return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), true, ret);
+}
+static inline void *ordered_hashmap_steal_first_key_and_value(OrderedHashmap *h, void **ret) {
+ return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), true, ret);
+}
+static inline void *hashmap_first_key_and_value(Hashmap *h, void **ret) {
+ return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), false, ret);
+}
+static inline void *ordered_hashmap_first_key_and_value(OrderedHashmap *h, void **ret) {
+ return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), false, ret);
+}
+
+
static inline void *hashmap_steal_first(Hashmap *h) {
- return internal_hashmap_steal_first(HASHMAP_BASE(h));
+ return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), true, NULL);
}
static inline void *ordered_hashmap_steal_first(OrderedHashmap *h) {
- return internal_hashmap_steal_first(HASHMAP_BASE(h));
+ return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), true, NULL);
+}
+static inline void *hashmap_first(Hashmap *h) {
+ return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), false, NULL);
+}
+static inline void *ordered_hashmap_first(OrderedHashmap *h) {
+ return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), false, NULL);
}
-void *internal_hashmap_steal_first_key(HashmapBase *h);
+static inline void *internal_hashmap_first_key(HashmapBase *h, bool remove) {
+ void *key = NULL;
+
+ (void) internal_hashmap_first_key_and_value(HASHMAP_BASE(h), remove, &key);
+ return key;
+}
static inline void *hashmap_steal_first_key(Hashmap *h) {
- return internal_hashmap_steal_first_key(HASHMAP_BASE(h));
+ return internal_hashmap_first_key(HASHMAP_BASE(h), true);
}
static inline void *ordered_hashmap_steal_first_key(OrderedHashmap *h) {
- return internal_hashmap_steal_first_key(HASHMAP_BASE(h));
+ return internal_hashmap_first_key(HASHMAP_BASE(h), true);
}
-
-void *internal_hashmap_first_key(HashmapBase *h) _pure_;
static inline void *hashmap_first_key(Hashmap *h) {
- return internal_hashmap_first_key(HASHMAP_BASE(h));
+ return internal_hashmap_first_key(HASHMAP_BASE(h), false);
}
static inline void *ordered_hashmap_first_key(OrderedHashmap *h) {
- return internal_hashmap_first_key(HASHMAP_BASE(h));
-}
-
-void *internal_hashmap_first(HashmapBase *h) _pure_;
-static inline void *hashmap_first(Hashmap *h) {
- return internal_hashmap_first(HASHMAP_BASE(h));
-}
-static inline void *ordered_hashmap_first(OrderedHashmap *h) {
- return internal_hashmap_first(HASHMAP_BASE(h));
+ return internal_hashmap_first_key(HASHMAP_BASE(h), false);
}
#define hashmap_clear_with_destructor(_s, _f) \
diff --git a/src/systemd/src/basic/list.h b/src/systemd/src/basic/list.h
index 643e0bea88..040680c30a 100644
--- a/src/systemd/src/basic/list.h
+++ b/src/systemd/src/basic/list.h
@@ -38,9 +38,9 @@
/* Append an item to the list */
#define LIST_APPEND(name,head,item) \
do { \
- typeof(*(head)) *_tail; \
- LIST_FIND_TAIL(name,head,_tail); \
- LIST_INSERT_AFTER(name,head,_tail,item); \
+ typeof(*(head)) **_hhead = &(head), *_tail; \
+ LIST_FIND_TAIL(name, *_hhead, _tail); \
+ LIST_INSERT_AFTER(name, *_hhead, _tail, item); \
} while (false)
/* Remove an item from the list */
diff --git a/src/systemd/src/basic/macro.h b/src/systemd/src/basic/macro.h
index 9972b6f992..ae88fa5b93 100644
--- a/src/systemd/src/basic/macro.h
+++ b/src/systemd/src/basic/macro.h
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
+#include <assert.h>
#include <inttypes.h>
#include <stdbool.h>
#include <sys/param.h>
@@ -56,10 +57,6 @@
#endif
/* Temporarily disable some warnings */
-#define DISABLE_WARNING_DECLARATION_AFTER_STATEMENT \
- _Pragma("GCC diagnostic push"); \
- _Pragma("GCC diagnostic ignored \"-Wdeclaration-after-statement\"")
-
#define DISABLE_WARNING_FORMAT_NONLITERAL \
_Pragma("GCC diagnostic push"); \
_Pragma("GCC diagnostic ignored \"-Wformat-nonliteral\"")
@@ -314,20 +311,13 @@ static inline int __coverity_check__(int condition) {
} while (false)
#if defined(static_assert)
-/* static_assert() is sometimes defined in a way that trips up
- * -Wdeclaration-after-statement, hence let's temporarily turn off
- * this warning around it. */
#define assert_cc(expr) \
- DISABLE_WARNING_DECLARATION_AFTER_STATEMENT; \
- static_assert(expr, #expr); \
- REENABLE_WARNING
+ static_assert(expr, #expr);
#else
#define assert_cc(expr) \
- DISABLE_WARNING_DECLARATION_AFTER_STATEMENT; \
struct CONCATENATE(_assert_struct_, __COUNTER__) { \
char x[(expr) ? 0 : -1]; \
- }; \
- REENABLE_WARNING
+ };
#endif
#define assert_return(expr, r) \
@@ -346,7 +336,7 @@ static inline int __coverity_check__(int condition) {
#define PTR_TO_INT(p) ((int) ((intptr_t) (p)))
#define INT_TO_PTR(u) ((void *) ((intptr_t) (u)))
-#define PTR_TO_UINT(p) ((unsigned int) ((uintptr_t) (p)))
+#define PTR_TO_UINT(p) ((unsigned) ((uintptr_t) (p)))
#define UINT_TO_PTR(u) ((void *) ((uintptr_t) (u)))
#define PTR_TO_LONG(p) ((long) ((intptr_t) (p)))
@@ -426,8 +416,11 @@ static inline int __coverity_check__(int condition) {
#define IN_SET(x, ...) \
({ \
bool _found = false; \
- /* If the build breaks in the line below, you need to extend the case macros */ \
- static _unused_ char _static_assert__macros_need_to_be_extended[20 - sizeof((int[]){__VA_ARGS__})/sizeof(int)]; \
+ /* If the build breaks in the line below, you need to extend the case macros. (We use "long double" as \
+ * type for the array, in the hope that checkers such as ubsan don't complain that the initializers for \
+ * the array are not representable by the base type. Ideally we'd use typeof(x) as base type, but that \
+ * doesn't work, as we want to use this on bitfields and gcc refuses typeof() on bitfields.) */ \
+ assert_cc((sizeof((long double[]){__VA_ARGS__})/sizeof(long double)) <= 20); \
switch(x) { \
FOR_EACH_MAKE_CASE(__VA_ARGS__) \
_found = true; \
diff --git a/src/systemd/src/basic/mempool.c b/src/systemd/src/basic/mempool.c
index a5ec8a1020..159c963377 100644
--- a/src/systemd/src/basic/mempool.c
+++ b/src/systemd/src/basic/mempool.c
@@ -3,8 +3,10 @@
#include <stdint.h>
#include <stdlib.h>
+#include "env-util.h"
#include "macro.h"
#include "mempool.h"
+#include "process-util.h"
#include "util.h"
struct pool {
@@ -70,8 +72,21 @@ void mempool_free_tile(struct mempool *mp, void *p) {
mp->freelist = p;
}
-#if VALGRIND
+bool mempool_enabled(void) {
+ static int b = -1;
+
+ if (!is_main_thread())
+ return false;
+ if (!mempool_use_allowed)
+ b = false;
+ if (b < 0)
+ b = getenv_bool("SYSTEMD_MEMPOOL") != 0;
+
+ return b;
+}
+
+#if VALGRIND
void mempool_drop(struct mempool *mp) {
struct pool *p = mp->first_pool;
while (p) {
@@ -81,5 +96,4 @@ void mempool_drop(struct mempool *mp) {
p = n;
}
}
-
#endif
diff --git a/src/systemd/src/basic/mempool.h b/src/systemd/src/basic/mempool.h
index 4098535c6f..0eecca0f92 100644
--- a/src/systemd/src/basic/mempool.h
+++ b/src/systemd/src/basic/mempool.h
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
+#include <stdbool.h>
#include <stddef.h>
struct pool;
@@ -22,6 +23,9 @@ static struct mempool pool_name = { \
.at_least = alloc_at_least, \
}
+extern const bool mempool_use_allowed;
+bool mempool_enabled(void);
+
#if VALGRIND
void mempool_drop(struct mempool *mp);
#endif
diff --git a/src/systemd/src/basic/path-util.c b/src/systemd/src/basic/path-util.c
index f3c6c16aae..2deb176240 100644
--- a/src/systemd/src/basic/path-util.c
+++ b/src/systemd/src/basic/path-util.c
@@ -333,12 +333,15 @@ char *path_simplify(char *path, bool kill_dots) {
/* Removes redundant inner and trailing slashes. Also removes unnecessary dots
* if kill_dots is true. Modifies the passed string in-place.
*
- * ///foo//./bar/. becomes /foo/./bar/. (if kill_dots is false)
- * ///foo//./bar/. becomes /foo/bar (if kill_dots is true)
- * .//./foo//./bar/. becomes ./foo/bar (if kill_dots is false)
- * .//./foo//./bar/. becomes foo/bar (if kill_dots is true)
+ * ///foo//./bar/. becomes /foo/./bar/. (if kill_dots is false)
+ * ///foo//./bar/. becomes /foo/bar (if kill_dots is true)
+ * .//./foo//./bar/. becomes ././foo/./bar/. (if kill_dots is false)
+ * .//./foo//./bar/. becomes foo/bar (if kill_dots is true)
*/
+ if (isempty(path))
+ return path;
+
absolute = path_is_absolute(path);
f = path;
@@ -368,9 +371,14 @@ char *path_simplify(char *path, bool kill_dots) {
*(t++) = *f;
}
- /* Special rule, if we are talking of the root directory, a trailing slash is good */
- if (absolute && t == path)
- *(t++) = '/';
+ /* Special rule, if we stripped everything, we either need a "/" (for the root directory)
+ * or "." for the current directory */
+ if (t == path) {
+ if (absolute)
+ *(t++) = '/';
+ else
+ *(t++) = '.';
+ }
*t = 0;
return path;
@@ -771,24 +779,32 @@ bool filename_is_valid(const char *p) {
if (*e != 0)
return false;
- if (e - p > FILENAME_MAX)
+ if (e - p > FILENAME_MAX) /* FILENAME_MAX is counted *without* the trailing NUL byte */
return false;
return true;
}
-bool path_is_normalized(const char *p) {
+bool path_is_valid(const char *p) {
if (isempty(p))
return false;
- if (dot_or_dot_dot(p))
+ if (strlen(p) >= PATH_MAX) /* PATH_MAX is counted *with* the trailing NUL byte */
return false;
- if (startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../"))
+ return true;
+}
+
+bool path_is_normalized(const char *p) {
+
+ if (!path_is_valid(p))
return false;
- if (strlen(p)+1 > PATH_MAX)
+ if (dot_or_dot_dot(p))
+ return false;
+
+ if (startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../"))
return false;
if (startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./"))
diff --git a/src/systemd/src/basic/path-util.h b/src/systemd/src/basic/path-util.h
index 49604eab80..17d31bbd89 100644
--- a/src/systemd/src/basic/path-util.h
+++ b/src/systemd/src/basic/path-util.h
@@ -134,6 +134,7 @@ char* dirname_malloc(const char *path);
const char *last_path_component(const char *path);
bool filename_is_valid(const char *p) _pure_;
+bool path_is_valid(const char *p) _pure_;
bool path_is_normalized(const char *p) _pure_;
char *file_in_same_dir(const char *path, const char *filename);
diff --git a/src/systemd/src/basic/prioq.c b/src/systemd/src/basic/prioq.c
index ef28a086d1..4ef4eaf0cd 100644
--- a/src/systemd/src/basic/prioq.c
+++ b/src/systemd/src/basic/prioq.c
@@ -32,11 +32,14 @@ struct Prioq {
Prioq *prioq_new(compare_func_t compare_func) {
Prioq *q;
- q = new0(Prioq, 1);
+ q = new(Prioq, 1);
if (!q)
return q;
- q->compare_func = compare_func;
+ *q = (Prioq) {
+ .compare_func = compare_func,
+ };
+
return q;
}
@@ -88,6 +91,7 @@ static void swap(Prioq *q, unsigned j, unsigned k) {
static unsigned shuffle_up(Prioq *q, unsigned idx) {
assert(q);
+ assert(idx < q->n_items);
while (idx > 0) {
unsigned k;
@@ -211,9 +215,12 @@ _pure_ static struct prioq_item* find_item(Prioq *q, void *data, unsigned *idx)
assert(q);
+ if (q->n_items <= 0)
+ return NULL;
+
if (idx) {
if (*idx == PRIOQ_IDX_NULL ||
- *idx > q->n_items)
+ *idx >= q->n_items)
return NULL;
i = q->items + *idx;
diff --git a/src/systemd/src/basic/prioq.h b/src/systemd/src/basic/prioq.h
index e036175260..bba5c7caa4 100644
--- a/src/systemd/src/basic/prioq.h
+++ b/src/systemd/src/basic/prioq.h
@@ -12,6 +12,7 @@ typedef struct Prioq Prioq;
Prioq *prioq_new(compare_func_t compare);
Prioq *prioq_free(Prioq *q);
+DEFINE_TRIVIAL_CLEANUP_FUNC(Prioq*, prioq_free);
int prioq_ensure_allocated(Prioq **q, compare_func_t compare_func);
int prioq_put(Prioq *q, void *data, unsigned *idx);
diff --git a/src/systemd/src/basic/process-util.c b/src/systemd/src/basic/process-util.c
index 1098cf453f..b2aab853e2 100644
--- a/src/systemd/src/basic/process-util.c
+++ b/src/systemd/src/basic/process-util.c
@@ -25,6 +25,7 @@
#include "alloc-util.h"
#include "architecture.h"
+#include "def.h"
#include "escape.h"
#include "fd-util.h"
#include "fileio.h"
@@ -336,15 +337,33 @@ int rename_process(const char name[]) {
/* Now, let's tell the kernel about this new memory */
if (prctl(PR_SET_MM, PR_SET_MM_ARG_START, (unsigned long) nn, 0, 0) < 0) {
- log_debug_errno(errno, "PR_SET_MM_ARG_START failed, proceeding without: %m");
- (void) munmap(nn, nn_size);
- goto use_saved_argv;
- }
+ /* HACK: prctl() API is kind of dumb on this point. The existing end address may already be
+ * below the desired start address, in which case the kernel may have kicked this back due
+ * to a range-check failure (see linux/kernel/sys.c:validate_prctl_map() to see this in
+ * action). The proper solution would be to have a prctl() API that could set both start+end
+ * simultaneously, or at least let us query the existing address to anticipate this condition
+ * and respond accordingly. For now, we can only guess at the cause of this failure and try
+ * a workaround--which will briefly expand the arg space to something potentially huge before
+ * resizing it to what we want. */
+ log_debug_errno(errno, "PR_SET_MM_ARG_START failed, attempting PR_SET_MM_ARG_END hack: %m");
+
+ if (prctl(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long) nn + l + 1, 0, 0) < 0) {
+ log_debug_errno(errno, "PR_SET_MM_ARG_END hack failed, proceeding without: %m");
+ (void) munmap(nn, nn_size);
+ goto use_saved_argv;
+ }
- /* And update the end pointer to the new end, too. If this fails, we don't really know what to do, it's
- * pretty unlikely that we can rollback, hence we'll just accept the failure, and continue. */
- if (prctl(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long) nn + l + 1, 0, 0) < 0)
- log_debug_errno(errno, "PR_SET_MM_ARG_END failed, proceeding without: %m");
+ if (prctl(PR_SET_MM, PR_SET_MM_ARG_START, (unsigned long) nn, 0, 0) < 0) {
+ log_debug_errno(errno, "PR_SET_MM_ARG_START still failed, proceeding without: %m");
+ goto use_saved_argv;
+ }
+ } else {
+ /* And update the end pointer to the new end, too. If this fails, we don't really know what
+ * to do, it's pretty unlikely that we can rollback, hence we'll just accept the failure,
+ * and continue. */
+ if (prctl(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long) nn + l + 1, 0, 0) < 0)
+ log_debug_errno(errno, "PR_SET_MM_ARG_END failed, proceeding without: %m");
+ }
if (mm)
(void) munmap(mm, mm_size);
@@ -496,8 +515,8 @@ int get_process_exe(pid_t pid, char **name) {
static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
_cleanup_fclose_ FILE *f = NULL;
- char line[LINE_MAX];
const char *p;
+ int r;
assert(field);
assert(uid);
@@ -515,9 +534,16 @@ static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
- FOREACH_LINE(line, f, return -errno) {
+ for (;;) {
+ _cleanup_free_ char *line = NULL;
char *l;
+ r = read_line(f, LONG_LINE_MAX, &line);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ break;
+
l = strstrip(line);
if (startswith(l, field)) {
diff --git a/src/systemd/src/basic/process-util.h b/src/systemd/src/basic/process-util.h
index 7ef45dc92b..ca4e4401a9 100644
--- a/src/systemd/src/basic/process-util.h
+++ b/src/systemd/src/basic/process-util.h
@@ -134,13 +134,6 @@ static inline bool pid_is_valid(pid_t p) {
return p > 0;
}
-static inline int sched_policy_to_string_alloc_with_check(int n, char **s) {
- if (!sched_policy_is_valid(n))
- return -EINVAL;
-
- return sched_policy_to_string_alloc(n, s);
-}
-
int ioprio_parse_priority(const char *s, int *ret);
pid_t getpid_cached(void);
@@ -166,7 +159,7 @@ static inline int safe_fork(const char *name, ForkFlags flags, pid_t *ret_pid) {
return safe_fork_full(name, NULL, 0, flags, ret_pid);
}
-int fork_agent(const char *name, const int except[], size_t n_except, pid_t *pid, const char *path, ...);
+int fork_agent(const char *name, const int except[], size_t n_except, pid_t *pid, const char *path, ...) _sentinel_;
int set_oom_score_adjust(int value);
diff --git a/src/systemd/src/basic/set.h b/src/systemd/src/basic/set.h
index 664713810d..0d99d5550d 100644
--- a/src/systemd/src/basic/set.h
+++ b/src/systemd/src/basic/set.h
@@ -86,7 +86,7 @@ static inline void set_clear_free(Set *s) {
/* no set_clear_free_free */
static inline void *set_steal_first(Set *s) {
- return internal_hashmap_steal_first(HASHMAP_BASE(s));
+ return internal_hashmap_first_key_and_value(HASHMAP_BASE(s), true, NULL);
}
#define set_clear_with_destructor(_s, _f) \
@@ -105,7 +105,7 @@ static inline void *set_steal_first(Set *s) {
/* no set_first_key */
static inline void *set_first(Set *s) {
- return internal_hashmap_first(HASHMAP_BASE(s));
+ return internal_hashmap_first_key_and_value(HASHMAP_BASE(s), false, NULL);
}
/* no set_next */
diff --git a/src/systemd/src/basic/siphash24.h b/src/systemd/src/basic/siphash24.h
index 54e2420cc6..70a4a03f6a 100644
--- a/src/systemd/src/basic/siphash24.h
+++ b/src/systemd/src/basic/siphash24.h
@@ -3,6 +3,7 @@
#include <inttypes.h>
#include <stddef.h>
#include <stdint.h>
+#include <string.h>
#include <sys/types.h>
struct siphash {
@@ -21,3 +22,7 @@ void siphash24_compress(const void *in, size_t inlen, struct siphash *state);
uint64_t siphash24_finalize(struct siphash *state);
uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[16]);
+
+static inline uint64_t siphash24_string(const char *s, const uint8_t k[16]) {
+ return siphash24(s, strlen(s) + 1, k);
+}
diff --git a/src/systemd/src/basic/socket-util.c b/src/systemd/src/basic/socket-util.c
index 4e8b2baf82..a156566511 100644
--- a/src/systemd/src/basic/socket-util.c
+++ b/src/systemd/src/basic/socket-util.c
@@ -57,8 +57,9 @@ int socket_address_parse(SocketAddress *a, const char *s) {
assert(a);
assert(s);
- zero(*a);
- a->type = SOCK_STREAM;
+ *a = (SocketAddress) {
+ .type = SOCK_STREAM,
+ };
if (*s == '[') {
uint16_t port;
@@ -96,7 +97,9 @@ int socket_address_parse(SocketAddress *a, const char *s) {
size_t l;
l = strlen(s);
- if (l >= sizeof(a->sockaddr.un.sun_path))
+ if (l >= sizeof(a->sockaddr.un.sun_path)) /* Note that we refuse non-NUL-terminated sockets when
+ * parsing (the kernel itself is less strict here in what it
+ * accepts) */
return -EINVAL;
a->sockaddr.un.sun_family = AF_UNIX;
@@ -108,7 +111,11 @@ int socket_address_parse(SocketAddress *a, const char *s) {
size_t l;
l = strlen(s+1);
- if (l >= sizeof(a->sockaddr.un.sun_path) - 1)
+ if (l >= sizeof(a->sockaddr.un.sun_path) - 1) /* Note that we refuse non-NUL-terminate sockets here
+ * when parsing, even though abstract namespace sockets
+ * explicitly allow embedded NUL bytes and don't consider
+ * them special. But it's simply annoying to debug such
+ * sockets. */
return -EINVAL;
a->sockaddr.un.sun_family = AF_UNIX;
@@ -286,19 +293,28 @@ int socket_address_verify(const SocketAddress *a) {
case AF_UNIX:
if (a->size < offsetof(struct sockaddr_un, sun_path))
return -EINVAL;
+ if (a->size > sizeof(struct sockaddr_un)+1) /* Allow one extra byte, since getsockname() on Linux will
+ * append a NUL byte if we have path sockets that are above
+ * sun_path' full size */
+ return -EINVAL;
- if (a->size > offsetof(struct sockaddr_un, sun_path)) {
-
- if (a->sockaddr.un.sun_path[0] != 0) {
- char *e;
+ if (a->size > offsetof(struct sockaddr_un, sun_path) &&
+ a->sockaddr.un.sun_path[0] != 0) { /* Only validate file system sockets here */
- /* path */
- e = memchr(a->sockaddr.un.sun_path, 0, sizeof(a->sockaddr.un.sun_path));
- if (!e)
- return -EINVAL;
+ const char *e;
+ e = memchr(a->sockaddr.un.sun_path, 0, sizeof(a->sockaddr.un.sun_path));
+ if (e) {
+ /* If there's an embedded NUL byte, make sure the size of the socket addresses matches it */
if (a->size != offsetof(struct sockaddr_un, sun_path) + (e - a->sockaddr.un.sun_path) + 1)
return -EINVAL;
+ } else {
+ /* If there's no embedded NUL byte, then then the size needs to match the whole
+ * structure or the structure with one extra NUL byte suffixed. (Yeah, Linux is awful,
+ * and considers both equivalent: getsockname() even extends sockaddr_un beyond its
+ * size if the path is non NUL terminated.)*/
+ if (!IN_SET(a->size, sizeof(a->sockaddr.un.sun_path), sizeof(a->sockaddr.un.sun_path)+1))
+ return -EINVAL;
}
}
@@ -482,6 +498,10 @@ const char* socket_address_get_path(const SocketAddress *a) {
if (a->sockaddr.un.sun_path[0] == 0)
return NULL;
+ /* Note that this is only safe because we know that there's an extra NUL byte after the sockaddr_un
+ * structure. On Linux AF_UNIX file system socket addresses don't have to be NUL terminated if they take up the
+ * full sun_path space. */
+ assert_cc(sizeof(union sockaddr_union) >= sizeof(struct sockaddr_un)+1);
return a->sockaddr.un.sun_path;
}
@@ -747,21 +767,6 @@ int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret)
return 0;
}
-int socket_address_unlink(SocketAddress *a) {
- assert(a);
-
- if (socket_address_family(a) != AF_UNIX)
- return 0;
-
- if (a->sockaddr.un.sun_path[0] == 0)
- return 0;
-
- if (unlink(a->sockaddr.un.sun_path) < 0)
- return -errno;
-
- return 1;
-}
-
static const char* const netlink_family_table[] = {
[NETLINK_ROUTE] = "route",
[NETLINK_FIREWALL] = "firewall",
@@ -834,10 +839,11 @@ int fd_inc_sndbuf(int fd, size_t n) {
/* If we have the privileges we will ignore the kernel limit. */
- value = (int) n;
- if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 0)
- if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &value, sizeof(value)) < 0)
- return -errno;
+ if (setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, n) < 0) {
+ r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, n);
+ if (r < 0)
+ return r;
+ }
return 1;
}
@@ -852,10 +858,12 @@ int fd_inc_rcvbuf(int fd, size_t n) {
/* If we have the privileges we will ignore the kernel limit. */
- value = (int) n;
- if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0)
- if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0)
- return -errno;
+ if (setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, n) < 0) {
+ r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, n);
+ if (r < 0)
+ return r;
+ }
+
return 1;
}
@@ -1246,3 +1254,71 @@ int socket_ioctl_fd(void) {
return fd;
}
+
+int sockaddr_un_unlink(const struct sockaddr_un *sa) {
+ const char *p, * nul;
+
+ assert(sa);
+
+ if (sa->sun_family != AF_UNIX)
+ return -EPROTOTYPE;
+
+ if (sa->sun_path[0] == 0) /* Nothing to do for abstract sockets */
+ return 0;
+
+ /* The path in .sun_path is not necessarily NUL terminated. Let's fix that. */
+ nul = memchr(sa->sun_path, 0, sizeof(sa->sun_path));
+ if (nul)
+ p = sa->sun_path;
+ else
+ p = memdupa_suffix0(sa->sun_path, sizeof(sa->sun_path));
+
+ if (unlink(p) < 0)
+ return -errno;
+
+ return 1;
+}
+
+int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path) {
+ size_t l;
+
+ assert(ret);
+ assert(path);
+
+ /* Initialize ret->sun_path from the specified argument. This will interpret paths starting with '@' as
+ * abstract namespace sockets, and those starting with '/' as regular filesystem sockets. It won't accept
+ * anything else (i.e. no relative paths), to avoid ambiguities. Note that this function cannot be used to
+ * reference paths in the abstract namespace that include NUL bytes in the name. */
+
+ l = strlen(path);
+ if (l == 0)
+ return -EINVAL;
+ if (!IN_SET(path[0], '/', '@'))
+ return -EINVAL;
+ if (path[1] == 0)
+ return -EINVAL;
+
+ /* Don't allow paths larger than the space in sockaddr_un. Note that we are a tiny bit more restrictive than
+ * the kernel is: we insist on NUL termination (both for abstract namespace and regular file system socket
+ * addresses!), which the kernel doesn't. We do this to reduce chance of incompatibility with other apps that
+ * do not expect non-NUL terminated file system path*/
+ if (l+1 > sizeof(ret->sun_path))
+ return -EINVAL;
+
+ *ret = (struct sockaddr_un) {
+ .sun_family = AF_UNIX,
+ };
+
+ if (path[0] == '@') {
+ /* Abstract namespace socket */
+ memcpy(ret->sun_path + 1, path + 1, l); /* copy *with* trailing NUL byte */
+ return (int) (offsetof(struct sockaddr_un, sun_path) + l); /* 🔥 *don't* 🔥 include trailing NUL in size */
+
+ } else {
+ assert(path[0] == '/');
+
+ /* File system socket */
+ memcpy(ret->sun_path, path, l + 1); /* copy *with* trailing NUL byte */
+ return (int) (offsetof(struct sockaddr_un, sun_path) + l + 1); /* include trailing NUL in size */
+ }
+}
diff --git a/src/systemd/src/basic/socket-util.h b/src/systemd/src/basic/socket-util.h
index 82781a0de1..8090e21657 100644
--- a/src/systemd/src/basic/socket-util.h
+++ b/src/systemd/src/basic/socket-util.h
@@ -71,7 +71,12 @@ int socket_address_parse_and_warn(SocketAddress *a, const char *s);
int socket_address_parse_netlink(SocketAddress *a, const char *s);
int socket_address_print(const SocketAddress *a, char **p);
int socket_address_verify(const SocketAddress *a) _pure_;
-int socket_address_unlink(SocketAddress *a);
+
+int sockaddr_un_unlink(const struct sockaddr_un *sa);
+
+static inline int socket_address_unlink(const SocketAddress *a) {
+ return socket_address_family(a) == AF_UNIX ? sockaddr_un_unlink(&a->sockaddr.un) : 0;
+}
bool socket_address_can_accept(const SocketAddress *a) _pure_;
@@ -179,7 +184,16 @@ struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t leng
offsetof(struct sockaddr_un, sun_path) + \
(_sa->sun_path[0] == 0 ? \
1 + strnlen(_sa->sun_path+1, sizeof(_sa->sun_path)-1) : \
- strnlen(_sa->sun_path, sizeof(_sa->sun_path))); \
+ strnlen(_sa->sun_path, sizeof(_sa->sun_path))+1); \
})
int socket_ioctl_fd(void);
+
+int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path);
+
+static inline int setsockopt_int(int fd, int level, int optname, int value) {
+ if (setsockopt(fd, level, optname, &value, sizeof(value)) < 0)
+ return -errno;
+
+ return 0;
+}
diff --git a/src/systemd/src/basic/string-util.c b/src/systemd/src/basic/string-util.c
index dfa739996f..05469ac01f 100644
--- a/src/systemd/src/basic/string-util.c
+++ b/src/systemd/src/basic/string-util.c
@@ -128,7 +128,7 @@ static size_t strcspn_escaped(const char *s, const char *reject) {
}
/* Split a string into words. */
-const char* split(const char **state, size_t *l, const char *separator, bool quoted) {
+const char* split(const char **state, size_t *l, const char *separator, SplitFlags flags) {
const char *current;
current = *state;
@@ -144,20 +144,24 @@ const char* split(const char **state, size_t *l, const char *separator, bool quo
return NULL;
}
- if (quoted && strchr("\'\"", *current)) {
+ if (flags & SPLIT_QUOTES && strchr("\'\"", *current)) {
char quotechars[2] = {*current, '\0'};
*l = strcspn_escaped(current + 1, quotechars);
if (current[*l + 1] == '\0' || current[*l + 1] != quotechars[0] ||
(current[*l + 2] && !strchr(separator, current[*l + 2]))) {
/* right quote missing or garbage at the end */
+ if (flags & SPLIT_RELAX) {
+ *state = current + *l + 1 + (current[*l + 1] != '\0');
+ return current + 1;
+ }
*state = current;
return NULL;
}
*state = current++ + *l + 2;
- } else if (quoted) {
+ } else if (flags & SPLIT_QUOTES) {
*l = strcspn_escaped(current, separator);
- if (current[*l] && !strchr(separator, current[*l])) {
+ if (current[*l] && !strchr(separator, current[*l]) && !(flags & SPLIT_RELAX)) {
/* unfinished escape */
*state = current;
return NULL;
@@ -394,12 +398,7 @@ int ascii_strcasecmp_nn(const char *a, size_t n, const char *b, size_t m) {
if (r != 0)
return r;
- if (n < m)
- return -1;
- else if (n > m)
- return 1;
- else
- return 0;
+ return CMP(n, m);
}
bool chars_intersect(const char *a, const char *b) {
@@ -1060,8 +1059,11 @@ typedef void *(*memset_t)(void *,int,size_t);
static volatile memset_t memset_func = memset;
-void explicit_bzero(void *p, size_t l) {
- memset_func(p, '\0', l);
+void* explicit_bzero_safe(void *p, size_t l) {
+ if (l > 0)
+ memset_func(p, '\0', l);
+
+ return p;
}
#endif
@@ -1071,7 +1073,7 @@ char* string_erase(char *x) {
/* A delicious drop of snake-oil! To be called on memory where
* we stored passphrases or so, after we used them. */
- explicit_bzero(x, strlen(x));
+ explicit_bzero_safe(x, strlen(x));
return x;
}
diff --git a/src/systemd/src/basic/string-util.h b/src/systemd/src/basic/string-util.h
index 72c075aa39..a5b5a16a5d 100644
--- a/src/systemd/src/basic/string-util.h
+++ b/src/systemd/src/basic/string-util.h
@@ -81,16 +81,21 @@ char *endswith_no_case(const char *s, const char *postfix) _pure_;
char *first_word(const char *s, const char *word) _pure_;
-const char* split(const char **state, size_t *l, const char *separator, bool quoted);
+typedef enum SplitFlags {
+ SPLIT_QUOTES = 0x01 << 0,
+ SPLIT_RELAX = 0x01 << 1,
+} SplitFlags;
+
+const char* split(const char **state, size_t *l, const char *separator, SplitFlags flags);
#define FOREACH_WORD(word, length, s, state) \
- _FOREACH_WORD(word, length, s, WHITESPACE, false, state)
+ _FOREACH_WORD(word, length, s, WHITESPACE, 0, state)
#define FOREACH_WORD_SEPARATOR(word, length, s, separator, state) \
- _FOREACH_WORD(word, length, s, separator, false, state)
+ _FOREACH_WORD(word, length, s, separator, 0, state)
-#define _FOREACH_WORD(word, length, s, separator, quoted, state) \
- for ((state) = (s), (word) = split(&(state), &(length), (separator), (quoted)); (word); (word) = split(&(state), &(length), (separator), (quoted)))
+#define _FOREACH_WORD(word, length, s, separator, flags, state) \
+ for ((state) = (s), (word) = split(&(state), &(length), (separator), (flags)); (word); (word) = split(&(state), &(length), (separator), (flags)))
char *strappend(const char *s, const char *suffix);
char *strnappend(const char *s, const char *suffix, size_t length);
@@ -193,8 +198,15 @@ static inline void *memmem_safe(const void *haystack, size_t haystacklen, const
return memmem(haystack, haystacklen, needle, needlelen);
}
-#if !HAVE_EXPLICIT_BZERO
-void explicit_bzero(void *p, size_t l);
+#if HAVE_EXPLICIT_BZERO
+static inline void* explicit_bzero_safe(void *p, size_t l) {
+ if (l > 0)
+ explicit_bzero(p, l);
+
+ return p;
+}
+#else
+void *explicit_bzero_safe(void *p, size_t l);
#endif
char *string_erase(char *x);
diff --git a/src/systemd/src/basic/strv.c b/src/systemd/src/basic/strv.c
index dc72f036ac..1bab723e88 100644
--- a/src/systemd/src/basic/strv.c
+++ b/src/systemd/src/basic/strv.c
@@ -245,7 +245,7 @@ int strv_extend_strv_concat(char ***a, char **b, const char *suffix) {
return 0;
}
-char **strv_split(const char *s, const char *separator) {
+char **strv_split_full(const char *s, const char *separator, SplitFlags flags) {
const char *word, *state;
size_t l;
size_t n, i;
@@ -253,12 +253,15 @@ char **strv_split(const char *s, const char *separator) {
assert(s);
+ if (!separator)
+ separator = WHITESPACE;
+
s += strspn(s, separator);
if (isempty(s))
return new0(char*, 1);
n = 0;
- FOREACH_WORD_SEPARATOR(word, l, s, separator, state)
+ _FOREACH_WORD(word, l, s, separator, flags, state)
n++;
r = new(char*, n+1);
@@ -266,7 +269,7 @@ char **strv_split(const char *s, const char *separator) {
return NULL;
i = 0;
- FOREACH_WORD_SEPARATOR(word, l, s, separator, state) {
+ _FOREACH_WORD(word, l, s, separator, flags, state) {
r[i] = strndup(word, l);
if (!r[i]) {
strv_free(r);
diff --git a/src/systemd/src/basic/strv.h b/src/systemd/src/basic/strv.h
index 34a660cb92..e9e6063f58 100644
--- a/src/systemd/src/basic/strv.h
+++ b/src/systemd/src/basic/strv.h
@@ -9,6 +9,7 @@
#include "alloc-util.h"
#include "extract-word.h"
#include "macro.h"
+#include "string-util.h"
#include "util.h"
char *strv_find(char **l, const char *name) _pure_;
@@ -66,7 +67,10 @@ static inline bool strv_isempty(char * const *l) {
return !l || !*l;
}
-char **strv_split(const char *s, const char *separator);
+char **strv_split_full(const char *s, const char *separator, SplitFlags flags);
+static inline char **strv_split(const char *s, const char *separator) {
+ return strv_split_full(s, separator, 0);
+}
char **strv_split_newlines(const char *s);
int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags);
diff --git a/src/systemd/src/basic/time-util.c b/src/systemd/src/basic/time-util.c
index 9ac739b42a..e351684219 100644
--- a/src/systemd/src/basic/time-util.c
+++ b/src/systemd/src/basic/time-util.c
@@ -14,6 +14,7 @@
#include <unistd.h>
#include "alloc-util.h"
+#include "def.h"
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
@@ -23,6 +24,7 @@
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
+#include "serialize.h"
#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
@@ -279,7 +281,7 @@ static char *format_timestamp_internal(
/* Let's not format times with years > 9999 */
if (t > USEC_TIMESTAMP_FORMATTABLE_MAX) {
- assert(l >= strlen("--- XXXX-XX-XX XX:XX:XX") + 1);
+ assert(l >= STRLEN("--- XXXX-XX-XX XX:XX:XX") + 1);
strcpy(buf, "--- XXXX-XX-XX XX:XX:XX");
return buf;
}
@@ -529,64 +531,6 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
return buf;
}
-void dual_timestamp_serialize(FILE *f, const char *name, dual_timestamp *t) {
-
- assert(f);
- assert(name);
- assert(t);
-
- if (!dual_timestamp_is_set(t))
- return;
-
- fprintf(f, "%s="USEC_FMT" "USEC_FMT"\n",
- name,
- t->realtime,
- t->monotonic);
-}
-
-int dual_timestamp_deserialize(const char *value, dual_timestamp *t) {
- uint64_t a, b;
- int r, pos;
-
- assert(value);
- assert(t);
-
- pos = strspn(value, WHITESPACE);
- if (value[pos] == '-')
- return -EINVAL;
- pos += strspn(value + pos, DIGITS);
- pos += strspn(value + pos, WHITESPACE);
- if (value[pos] == '-')
- return -EINVAL;
-
- r = sscanf(value, "%" PRIu64 "%" PRIu64 "%n", &a, &b, &pos);
- if (r != 2) {
- log_debug("Failed to parse dual timestamp value \"%s\".", value);
- return -EINVAL;
- }
-
- if (value[pos] != '\0')
- /* trailing garbage */
- return -EINVAL;
-
- t->realtime = a;
- t->monotonic = b;
-
- return 0;
-}
-
-int timestamp_deserialize(const char *value, usec_t *timestamp) {
- int r;
-
- assert(value);
-
- r = safe_atou64(value, timestamp);
- if (r < 0)
- return log_debug_errno(r, "Failed to parse timestamp value \"%s\": %m", value);
-
- return r;
-}
-
static int parse_timestamp_impl(const char *t, usec_t *usec, bool with_tz) {
static const struct {
const char *name;
@@ -1025,7 +969,7 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
char *b = e + 1;
/* Don't allow "0.-0", "3.+1" or "3. 1" */
- if (*b == '-' || *b == '+' || isspace(*b))
+ if (IN_SET(*b, '-', '+') || isspace(*b))
return -EINVAL;
errno = 0;
@@ -1047,12 +991,21 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
something = true;
+
+ k = ((usec_t) -1) / multiplier;
+ if ((usec_t) l + 1 >= k || (usec_t) z >= k)
+ return -ERANGE;
+
k = (usec_t) z * multiplier;
for (; n > 0; n--)
k /= 10;
- r += (usec_t) l * multiplier + k;
+ k += (usec_t) l * multiplier;
+ if (k >= ((usec_t) -1) - r)
+ return -ERANGE;
+
+ r += k;
}
*usec = r;
@@ -1064,18 +1017,19 @@ int parse_sec(const char *t, usec_t *usec) {
return parse_time(t, usec, USEC_PER_SEC);
}
-int parse_sec_fix_0(const char *t, usec_t *usec) {
- assert(t);
- assert(usec);
+int parse_sec_fix_0(const char *t, usec_t *ret) {
+ usec_t k;
+ int r;
- t += strspn(t, WHITESPACE);
+ assert(t);
+ assert(ret);
- if (streq(t, "0")) {
- *usec = USEC_INFINITY;
- return 0;
- }
+ r = parse_sec(t, &k);
+ if (r < 0)
+ return r;
- return parse_sec(t, usec);
+ *ret = k == 0 ? USEC_INFINITY : k;
+ return r;
}
int parse_nsec(const char *t, nsec_t *nsec) {
@@ -1163,7 +1117,7 @@ int parse_nsec(const char *t, nsec_t *nsec) {
if (*e == '.') {
char *b = e + 1;
- if (*b == '-' || *b == '+' || isspace(*b))
+ if (IN_SET(*b, '-', '+') || isspace(*b))
return -EINVAL;
errno = 0;
@@ -1184,12 +1138,22 @@ int parse_nsec(const char *t, nsec_t *nsec) {
for (i = 0; i < ELEMENTSOF(table); i++)
if (startswith(e, table[i].suffix)) {
- nsec_t k = (nsec_t) z * table[i].nsec;
+ nsec_t k;
+
+ k = ((nsec_t) -1) / table[i].nsec;
+ if ((nsec_t) l + 1 >= k || (nsec_t) z >= k)
+ return -ERANGE;
+
+ k = (nsec_t) z * table[i].nsec;
for (; n > 0; n--)
k /= 10;
- r += (nsec_t) l * table[i].nsec + k;
+ k += (nsec_t) l * table[i].nsec;
+ if (k >= ((nsec_t) -1) - r)
+ return -ERANGE;
+
+ r += k;
p = e + strlen(table[i].suffix);
something = true;
@@ -1222,6 +1186,7 @@ int get_timezones(char ***ret) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_strv_free_ char **zones = NULL;
size_t n_zones = 0, n_allocated = 0;
+ int r;
assert(ret);
@@ -1234,13 +1199,18 @@ int get_timezones(char ***ret) {
f = fopen("/usr/share/zoneinfo/zone.tab", "re");
if (f) {
- char l[LINE_MAX];
-
- FOREACH_LINE(l, f, return -errno) {
+ for (;;) {
+ _cleanup_free_ char *line = NULL;
char *p, *w;
size_t k;
- p = strstrip(l);
+ r = read_line(f, LONG_LINE_MAX, &line);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ break;
+
+ p = strstrip(line);
if (isempty(p) || *p == '#')
continue;
diff --git a/src/systemd/src/basic/time-util.h b/src/systemd/src/basic/time-util.h
index 344f2dc52e..5316305062 100644
--- a/src/systemd/src/basic/time-util.h
+++ b/src/systemd/src/basic/time-util.h
@@ -108,10 +108,6 @@ char *format_timestamp_us_utc(char *buf, size_t l, usec_t t);
char *format_timestamp_relative(char *buf, size_t l, usec_t t);
char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy);
-void dual_timestamp_serialize(FILE *f, const char *name, dual_timestamp *t);
-int dual_timestamp_deserialize(const char *value, dual_timestamp *t);
-int timestamp_deserialize(const char *value, usec_t *timestamp);
-
int parse_timestamp(const char *t, usec_t *usec);
int parse_sec(const char *t, usec_t *usec);
diff --git a/src/systemd/src/basic/util.c b/src/systemd/src/basic/util.c
index 081c63c898..0da963f4af 100644
--- a/src/systemd/src/basic/util.c
+++ b/src/systemd/src/basic/util.c
@@ -23,6 +23,7 @@
#include "def.h"
#include "device-nodes.h"
#include "dirent-util.h"
+#include "env-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "format-util.h"
@@ -106,6 +107,7 @@ int prot_from_flags(int flags) {
bool in_initrd(void) {
struct statfs s;
+ int r;
if (saved_in_initrd >= 0)
return saved_in_initrd;
@@ -120,9 +122,16 @@ bool in_initrd(void) {
* emptying when transititioning to the main systemd.
*/
- saved_in_initrd = access("/etc/initrd-release", F_OK) >= 0 &&
- statfs("/", &s) >= 0 &&
- is_temporary_fs(&s);
+ r = getenv_bool_secure("SYSTEMD_IN_INITRD");
+ if (r < 0 && r != -ENXIO)
+ log_debug_errno(r, "Failed to parse $SYSTEMD_IN_INITRD, ignoring: %m");
+
+ if (r >= 0)
+ saved_in_initrd = r > 0;
+ else
+ saved_in_initrd = access("/etc/initrd-release", F_OK) >= 0 &&
+ statfs("/", &s) >= 0 &&
+ is_temporary_fs(&s);
return saved_in_initrd;
}
diff --git a/src/systemd/src/basic/util.h b/src/systemd/src/basic/util.h
index 5f3f982190..8cba4ed726 100644
--- a/src/systemd/src/basic/util.h
+++ b/src/systemd/src/basic/util.h
@@ -150,7 +150,13 @@ static inline int memcmp_safe(const void *s1, const void *s2, size_t n) {
int on_ac_power(void);
-#define memzero(x,l) (memset((x), 0, (l)))
+#define memzero(x,l) \
+ ({ \
+ size_t _l_ = (l); \
+ void *_x_ = (x); \
+ _l_ == 0 ? _x_ : memset(_x_, 0, _l_); \
+ })
+
#define zero(x) (memzero(&(x), sizeof(x)))
static inline void *mempset(void *s, int c, size_t n) {
diff --git a/src/systemd/src/libsystemd-network/dhcp-network.c b/src/systemd/src/libsystemd-network/dhcp-network.c
index cf59f14958..0e5b4147a9 100644
--- a/src/systemd/src/libsystemd-network/dhcp-network.c
+++ b/src/systemd/src/libsystemd-network/dhcp-network.c
@@ -78,7 +78,7 @@ static int _bind_raw_socket(int ifindex, union sockaddr_union *link,
.filter = filter
};
_cleanup_close_ int s = -1;
- int r, on = 1;
+ int r;
assert(ifindex > 0);
assert(link);
@@ -87,9 +87,9 @@ static int _bind_raw_socket(int ifindex, union sockaddr_union *link,
if (s < 0)
return -errno;
- r = setsockopt(s, SOL_PACKET, PACKET_AUXDATA, &on, sizeof(on));
+ r = setsockopt_int(s, SOL_PACKET, PACKET_AUXDATA, true);
if (r < 0)
- return -errno;
+ return r;
r = setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog));
if (r < 0)
@@ -149,19 +149,19 @@ int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port) {
};
_cleanup_close_ int s = -1;
char ifname[IF_NAMESIZE] = "";
- int r, on = 1, tos = IPTOS_CLASS_CS6;
+ int r;
s = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
if (s < 0)
return -errno;
- r = setsockopt(s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
+ r = setsockopt_int(s, IPPROTO_IP, IP_TOS, IPTOS_CLASS_CS6);
if (r < 0)
- return -errno;
+ return r;
- r = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+ r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true);
if (r < 0)
- return -errno;
+ return r;
if (ifindex > 0) {
if (if_indextoname(ifindex, ifname) == 0)
@@ -173,18 +173,18 @@ int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port) {
}
if (address == INADDR_ANY) {
- r = setsockopt(s, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on));
+ r = setsockopt_int(s, IPPROTO_IP, IP_PKTINFO, true);
if (r < 0)
- return -errno;
+ return r;
- r = setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
+ r = setsockopt_int(s, SOL_SOCKET, SO_BROADCAST, true);
if (r < 0)
- return -errno;
+ return r;
} else {
- r = setsockopt(s, IPPROTO_IP, IP_FREEBIND, &on, sizeof(on));
+ r = setsockopt_int(s, IPPROTO_IP, IP_FREEBIND, true);
if (r < 0)
- return -errno;
+ return r;
}
r = bind(s, &src.sa, sizeof(src.in));
diff --git a/src/systemd/src/libsystemd-network/dhcp6-internal.h b/src/systemd/src/libsystemd-network/dhcp6-internal.h
index 63d8fe35f8..157fc0aadd 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-internal.h
+++ b/src/systemd/src/libsystemd-network/dhcp6-internal.h
@@ -84,8 +84,8 @@ typedef struct DHCP6IA DHCP6IA;
int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code,
size_t optlen, const void *optval);
-int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia);
-int dhcp6_option_append_pd(uint8_t *buf, size_t len, DHCP6IA *pd);
+int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia);
+int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd);
int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn);
int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode,
size_t *optlen, uint8_t **optvalue);
diff --git a/src/systemd/src/libsystemd-network/dhcp6-network.c b/src/systemd/src/libsystemd-network/dhcp6-network.c
index 78cd383669..580f43ba40 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-network.c
+++ b/src/systemd/src/libsystemd-network/dhcp6-network.c
@@ -25,7 +25,7 @@ int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) {
.in6.sin6_scope_id = index,
};
_cleanup_close_ int s = -1;
- int r, off = 0, on = 1;
+ int r;
assert(index > 0);
assert(local_address);
@@ -36,17 +36,17 @@ int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) {
if (s < 0)
return -errno;
- r = setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
+ r = setsockopt_int(s, IPPROTO_IPV6, IPV6_V6ONLY, true);
if (r < 0)
- return -errno;
+ return r;
- r = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &off, sizeof(off));
+ r = setsockopt_int(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, false);
if (r < 0)
- return -errno;
+ return r;
- r = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+ r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true);
if (r < 0)
- return -errno;
+ return r;
r = bind(s, &src.sa, sizeof(src.in6));
if (r < 0)
diff --git a/src/systemd/src/libsystemd-network/dhcp6-option.c b/src/systemd/src/libsystemd-network/dhcp6-option.c
index cf19d366d3..a2aac9a793 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-option.c
+++ b/src/systemd/src/libsystemd-network/dhcp6-option.c
@@ -37,9 +37,9 @@ typedef struct DHCP6PDPrefixOption {
uint8_t options[];
} _packed_ DHCP6PDPrefixOption;
-#define DHCP6_OPTION_IA_NA_LEN (sizeof(struct ia_na))
-#define DHCP6_OPTION_IA_PD_LEN (sizeof(struct ia_pd))
-#define DHCP6_OPTION_IA_TA_LEN (sizeof(struct ia_ta))
+#define DHCP6_OPTION_IA_NA_LEN (sizeof(struct ia_na))
+#define DHCP6_OPTION_IA_PD_LEN (sizeof(struct ia_pd))
+#define DHCP6_OPTION_IA_TA_LEN (sizeof(struct ia_ta))
static int option_append_hdr(uint8_t **buf, size_t *buflen, uint16_t optcode,
size_t optlen) {
@@ -49,14 +49,14 @@ static int option_append_hdr(uint8_t **buf, size_t *buflen, uint16_t optcode,
assert_return(*buf, -EINVAL);
assert_return(buflen, -EINVAL);
- if (optlen > 0xffff || *buflen < optlen + sizeof(DHCP6Option))
+ if (optlen > 0xffff || *buflen < optlen + offsetof(DHCP6Option, data))
return -ENOBUFS;
option->code = htobe16(optcode);
option->len = htobe16(optlen);
- *buf += sizeof(DHCP6Option);
- *buflen -= sizeof(DHCP6Option);
+ *buf += offsetof(DHCP6Option, data);
+ *buflen -= offsetof(DHCP6Option, data);
return 0;
}
@@ -79,14 +79,17 @@ int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code,
return 0;
}
-int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) {
+int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia) {
uint16_t len;
uint8_t *ia_hdr;
size_t iaid_offset, ia_buflen, ia_addrlen = 0;
DHCP6Address *addr;
int r;
- assert_return(buf && *buf && buflen && ia, -EINVAL);
+ assert_return(buf, -EINVAL);
+ assert_return(*buf, -EINVAL);
+ assert_return(buflen, -EINVAL);
+ assert_return(ia, -EINVAL);
switch (ia->type) {
case SD_DHCP6_OPTION_IA_NA:
@@ -103,14 +106,14 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) {
return -EINVAL;
}
- if (*buflen < len)
+ if (*buflen < offsetof(DHCP6Option, data) + len)
return -ENOBUFS;
ia_hdr = *buf;
ia_buflen = *buflen;
- *buf += sizeof(DHCP6Option);
- *buflen -= sizeof(DHCP6Option);
+ *buf += offsetof(DHCP6Option, data);
+ *buflen -= offsetof(DHCP6Option, data);
memcpy(*buf, (char*) ia + iaid_offset, len);
@@ -128,7 +131,7 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) {
*buf += sizeof(addr->iaaddr);
*buflen -= sizeof(addr->iaaddr);
- ia_addrlen += sizeof(DHCP6Option) + sizeof(addr->iaaddr);
+ ia_addrlen += offsetof(DHCP6Option, data) + sizeof(addr->iaaddr);
}
r = option_append_hdr(&ia_hdr, &ia_buflen, ia->type, len + ia_addrlen);
@@ -165,7 +168,7 @@ int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn) {
return r;
}
-int dhcp6_option_append_pd(uint8_t *buf, size_t len, DHCP6IA *pd) {
+int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd) {
DHCP6Option *option = (DHCP6Option *)buf;
size_t i = sizeof(*option) + sizeof(pd->ia_pd);
DHCP6Address *prefix;
@@ -210,7 +213,7 @@ static int option_parse_hdr(uint8_t **buf, size_t *buflen, uint16_t *optcode, si
assert_return(optcode, -EINVAL);
assert_return(optlen, -EINVAL);
- if (*buflen < sizeof(DHCP6Option))
+ if (*buflen < offsetof(DHCP6Option, data))
return -ENOMSG;
len = be16toh(option->len);
@@ -251,7 +254,7 @@ int dhcp6_option_parse_status(DHCP6Option *option, size_t len) {
DHCP6StatusOption *statusopt = (DHCP6StatusOption *)option;
if (len < sizeof(DHCP6StatusOption) ||
- be16toh(option->len) + sizeof(DHCP6Option) < sizeof(DHCP6StatusOption))
+ be16toh(option->len) + offsetof(DHCP6Option, data) < sizeof(DHCP6StatusOption))
return -ENOBUFS;
return be16toh(statusopt->status);
@@ -264,7 +267,7 @@ static int dhcp6_option_parse_address(DHCP6Option *option, DHCP6IA *ia,
uint32_t lt_valid, lt_pref;
int r;
- if (be16toh(option->len) + sizeof(DHCP6Option) < sizeof(*addr_option))
+ if (be16toh(option->len) + offsetof(DHCP6Option, data) < sizeof(*addr_option))
return -ENOBUFS;
lt_valid = be32toh(addr_option->iaaddr.lifetime_valid);
@@ -277,8 +280,8 @@ static int dhcp6_option_parse_address(DHCP6Option *option, DHCP6IA *ia,
return 0;
}
- if (be16toh(option->len) + sizeof(DHCP6Option) > sizeof(*addr_option)) {
- r = dhcp6_option_parse_status((DHCP6Option *)addr_option->options, be16toh(option->len) + sizeof(DHCP6Option) - sizeof(*addr_option));
+ if (be16toh(option->len) + offsetof(DHCP6Option, data) > sizeof(*addr_option)) {
+ r = dhcp6_option_parse_status((DHCP6Option *)addr_option->options, be16toh(option->len) + offsetof(DHCP6Option, data) - sizeof(*addr_option));
if (r != 0)
return r < 0 ? r: 0;
}
@@ -304,7 +307,7 @@ static int dhcp6_option_parse_pdprefix(DHCP6Option *option, DHCP6IA *ia,
uint32_t lt_valid, lt_pref;
int r;
- if (be16toh(option->len) + sizeof(DHCP6Option) < sizeof(*pdprefix_option))
+ if (be16toh(option->len) + offsetof(DHCP6Option, data) < sizeof(*pdprefix_option))
return -ENOBUFS;
lt_valid = be32toh(pdprefix_option->iapdprefix.lifetime_valid);
@@ -317,8 +320,8 @@ static int dhcp6_option_parse_pdprefix(DHCP6Option *option, DHCP6IA *ia,
return 0;
}
- if (be16toh(option->len) + sizeof(DHCP6Option) > sizeof(*pdprefix_option)) {
- r = dhcp6_option_parse_status((DHCP6Option *)pdprefix_option->options, be16toh(option->len) + sizeof(DHCP6Option) - sizeof(*pdprefix_option));
+ if (be16toh(option->len) + offsetof(DHCP6Option, data) > sizeof(*pdprefix_option)) {
+ r = dhcp6_option_parse_status((DHCP6Option *)pdprefix_option->options, be16toh(option->len) + offsetof(DHCP6Option, data) - sizeof(*pdprefix_option));
if (r != 0)
return r < 0 ? r: 0;
}
@@ -354,10 +357,8 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) {
switch (iatype) {
case SD_DHCP6_OPTION_IA_NA:
- if (len < DHCP6_OPTION_IA_NA_LEN) {
- r = -ENOBUFS;
- goto error;
- }
+ if (len < DHCP6_OPTION_IA_NA_LEN)
+ return -ENOBUFS;
iaaddr_offset = DHCP6_OPTION_IA_NA_LEN;
memcpy(&ia->ia_na, iaoption->data, sizeof(ia->ia_na));
@@ -368,18 +369,15 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) {
if (lt_t1 && lt_t2 && lt_t1 > lt_t2) {
log_dhcp6_client(client, "IA NA T1 %ds > T2 %ds",
lt_t1, lt_t2);
- r = -EINVAL;
- goto error;
+ return -EINVAL;
}
break;
case SD_DHCP6_OPTION_IA_PD:
- if (len < sizeof(ia->ia_pd)) {
- r = -ENOBUFS;
- goto error;
- }
+ if (len < sizeof(ia->ia_pd))
+ return -ENOBUFS;
iaaddr_offset = sizeof(ia->ia_pd);
memcpy(&ia->ia_pd, iaoption->data, sizeof(ia->ia_pd));
@@ -390,17 +388,14 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) {
if (lt_t1 && lt_t2 && lt_t1 > lt_t2) {
log_dhcp6_client(client, "IA PD T1 %ds > T2 %ds",
lt_t1, lt_t2);
- r = -EINVAL;
- goto error;
+ return -EINVAL;
}
break;
case SD_DHCP6_OPTION_IA_TA:
- if (len < DHCP6_OPTION_IA_TA_LEN) {
- r = -ENOBUFS;
- goto error;
- }
+ if (len < DHCP6_OPTION_IA_TA_LEN)
+ return -ENOBUFS;
iaaddr_offset = DHCP6_OPTION_IA_TA_LEN;
memcpy(&ia->ia_ta.id, iaoption->data, sizeof(ia->ia_ta));
@@ -408,8 +403,7 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) {
break;
default:
- r = -ENOMSG;
- goto error;
+ return -ENOMSG;
}
ia->type = iatype;
@@ -418,10 +412,8 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) {
while (i < len) {
DHCP6Option *option = (DHCP6Option *)&iaoption->data[i];
- if (len < i + sizeof(*option) || len < i + sizeof(*option) + be16toh(option->len)) {
- r = -ENOBUFS;
- goto error;
- }
+ if (len < i + sizeof(*option) || len < i + sizeof(*option) + be16toh(option->len))
+ return -ENOBUFS;
opt = be16toh(option->code);
optlen = be16toh(option->len);
@@ -431,13 +423,12 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) {
if (!IN_SET(ia->type, SD_DHCP6_OPTION_IA_NA, SD_DHCP6_OPTION_IA_TA)) {
log_dhcp6_client(client, "IA Address option not in IA NA or TA option");
- r = -EINVAL;
- goto error;
+ return -EINVAL;
}
r = dhcp6_option_parse_address(option, ia, &lt_valid);
if (r < 0)
- goto error;
+ return r;
if (lt_valid < lt_min)
lt_min = lt_valid;
@@ -448,13 +439,12 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) {
if (!IN_SET(ia->type, SD_DHCP6_OPTION_IA_PD)) {
log_dhcp6_client(client, "IA PD Prefix option not in IA PD option");
- r = -EINVAL;
- goto error;
+ return -EINVAL;
}
r = dhcp6_option_parse_pdprefix(option, ia, &lt_valid);
if (r < 0)
- goto error;
+ return r;
if (lt_valid < lt_min)
lt_min = lt_valid;
@@ -463,15 +453,14 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) {
case SD_DHCP6_OPTION_STATUS_CODE:
- status = dhcp6_option_parse_status(option, optlen);
- if (status) {
+ status = dhcp6_option_parse_status(option, optlen + offsetof(DHCP6Option, data));
+ if (status < 0)
+ return status;
+ if (status > 0) {
log_dhcp6_client(client, "IA status %d",
status);
- dhcp6_lease_free_ia(ia);
-
- r = -EINVAL;
- goto error;
+ return -EINVAL;
}
break;
@@ -515,8 +504,7 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) {
break;
}
-error:
- return r;
+ return 0;
}
int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen,
@@ -551,6 +539,7 @@ int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char *
bool first = true;
for (;;) {
+ const char *label;
uint8_t c;
c = optval[pos++];
@@ -558,47 +547,41 @@ int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char *
if (c == 0)
/* End of name */
break;
- else if (c <= 63) {
- const char *label;
-
- /* Literal label */
- label = (const char *)&optval[pos];
- pos += c;
- if (pos >= optlen)
- return -EMSGSIZE;
-
- if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)) {
- r = -ENOMEM;
- goto fail;
- }
-
- if (first)
- first = false;
- else
- ret[n++] = '.';
-
- r = dns_label_escape(label, c, ret + n, DNS_LABEL_ESCAPED_MAX);
- if (r < 0)
- goto fail;
-
- n += r;
- continue;
- } else {
- r = -EBADMSG;
- goto fail;
- }
- }
+ if (c > 63)
+ return -EBADMSG;
+
+ /* Literal label */
+ label = (const char *)&optval[pos];
+ pos += c;
+ if (pos >= optlen)
+ return -EMSGSIZE;
+
+ if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX))
+ return -ENOMEM;
+
+ if (first)
+ first = false;
+ else
+ ret[n++] = '.';
- if (!GREEDY_REALLOC(ret, allocated, n + 1)) {
- r = -ENOMEM;
- goto fail;
+ r = dns_label_escape(label, c, ret + n, DNS_LABEL_ESCAPED_MAX);
+ if (r < 0)
+ return r;
+
+ n += r;
}
+ if (n == 0)
+ continue;
+
+ if (!GREEDY_REALLOC(ret, allocated, n + 1))
+ return -ENOMEM;
+
ret[n] = 0;
r = strv_extend(&names, ret);
if (r < 0)
- goto fail;
+ return r;
idx++;
}
@@ -606,7 +589,4 @@ int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char *
*str_arr = TAKE_PTR(names);
return idx;
-
-fail:
- return r;
}
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-client.c b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
index 3e8d985aa7..dde2d0ceb0 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
@@ -86,7 +86,7 @@ struct sd_dhcp_client {
uint32_t mtu;
uint32_t xid;
usec_t start_time;
- unsigned int attempt;
+ unsigned attempt;
usec_t request_sent;
sd_event_source *timeout_t1;
sd_event_source *timeout_t2;
@@ -1683,6 +1683,8 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, i
client->timeout_resend =
sd_event_source_unref(client->timeout_resend);
+ client_notify(client, SD_DHCP_CLIENT_EVENT_EXPIRED);
+
r = client_initialize(client);
if (r < 0)
goto error;
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
index c07d831f7d..2ddfead4b0 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
@@ -829,10 +829,11 @@ static int client_parse_message(
DHCP6Message *message,
size_t len,
sd_dhcp6_lease *lease) {
+
+ uint32_t lt_t1 = ~0, lt_t2 = ~0;
+ bool clientid = false;
size_t pos = 0;
int r;
- bool clientid = false;
- uint32_t lt_t1 = ~0, lt_t2 = ~0;
assert(client);
assert(message);
@@ -842,20 +843,22 @@ static int client_parse_message(
len -= sizeof(DHCP6Message);
while (pos < len) {
- DHCP6Option *option = (DHCP6Option *)&message->options[pos];
+ DHCP6Option *option = (DHCP6Option *) &message->options[pos];
uint16_t optcode, optlen;
- int status;
- uint8_t *optval;
be32_t iaid_lease;
+ uint8_t *optval;
+ int status;
- if (len < pos + offsetof(DHCP6Option, data) ||
- len < pos + offsetof(DHCP6Option, data) + be16toh(option->len))
+ if (len < pos + offsetof(DHCP6Option, data))
return -ENOBUFS;
optcode = be16toh(option->code);
optlen = be16toh(option->len);
optval = option->data;
+ if (len < pos + offsetof(DHCP6Option, data) + optlen)
+ return -ENOBUFS;
+
switch (optcode) {
case SD_DHCP6_OPTION_CLIENTID:
if (clientid) {
@@ -900,13 +903,14 @@ static int client_parse_message(
break;
case SD_DHCP6_OPTION_STATUS_CODE:
- status = dhcp6_option_parse_status(option, optlen);
- if (status) {
+ status = dhcp6_option_parse_status(option, optlen + sizeof(DHCP6Option));
+ if (status < 0)
+ return status;
+
+ if (status > 0) {
log_dhcp6_client(client, "%s Status %s",
dhcp6_message_type_to_string(message->type),
dhcp6_message_status_to_string(status));
- dhcp6_lease_free_ia(&lease->ia);
- dhcp6_lease_free_ia(&lease->pd);
return -EINVAL;
}
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c
index 15fec2d851..8b424811ad 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c
@@ -52,15 +52,16 @@ DHCP6IA *dhcp6_lease_free_ia(DHCP6IA *ia) {
int dhcp6_lease_set_serverid(sd_dhcp6_lease *lease, const uint8_t *id,
size_t len) {
+ uint8_t *serverid;
+
assert_return(lease, -EINVAL);
assert_return(id, -EINVAL);
- free(lease->serverid);
-
- lease->serverid = memdup(id, len);
- if (!lease->serverid)
- return -EINVAL;
+ serverid = memdup(id, len);
+ if (!serverid)
+ return -ENOMEM;
+ free_and_replace(lease->serverid, serverid);
lease->serverid_len = len;
return 0;
diff --git a/src/systemd/src/libsystemd/sd-event/sd-event.c b/src/systemd/src/libsystemd/sd-event/sd-event.c
index 880e127686..f44e6b4cca 100644
--- a/src/systemd/src/libsystemd/sd-event/sd-event.c
+++ b/src/systemd/src/libsystemd/sd-event/sd-event.c
@@ -314,6 +314,7 @@ static sd_event *event_resolve(sd_event *e) {
static int pending_prioq_compare(const void *a, const void *b) {
const sd_event_source *x = a, *y = b;
+ int r;
assert(x->pending);
assert(y->pending);
@@ -325,22 +326,17 @@ static int pending_prioq_compare(const void *a, const void *b) {
return 1;
/* Lower priority values first */
- if (x->priority < y->priority)
- return -1;
- if (x->priority > y->priority)
- return 1;
+ r = CMP(x->priority, y->priority);
+ if (r != 0)
+ return r;
/* Older entries first */
- if (x->pending_iteration < y->pending_iteration)
- return -1;
- if (x->pending_iteration > y->pending_iteration)
- return 1;
-
- return 0;
+ return CMP(x->pending_iteration, y->pending_iteration);
}
static int prepare_prioq_compare(const void *a, const void *b) {
const sd_event_source *x = a, *y = b;
+ int r;
assert(x->prepare);
assert(y->prepare);
@@ -354,18 +350,12 @@ static int prepare_prioq_compare(const void *a, const void *b) {
/* Move most recently prepared ones last, so that we can stop
* preparing as soon as we hit one that has already been
* prepared in the current iteration */
- if (x->prepare_iteration < y->prepare_iteration)
- return -1;
- if (x->prepare_iteration > y->prepare_iteration)
- return 1;
+ r = CMP(x->prepare_iteration, y->prepare_iteration);
+ if (r != 0)
+ return r;
/* Lower priority values first */
- if (x->priority < y->priority)
- return -1;
- if (x->priority > y->priority)
- return 1;
-
- return 0;
+ return CMP(x->priority, y->priority);
}
static int earliest_time_prioq_compare(const void *a, const void *b) {
@@ -387,12 +377,7 @@ static int earliest_time_prioq_compare(const void *a, const void *b) {
return 1;
/* Order by time */
- if (x->time.next < y->time.next)
- return -1;
- if (x->time.next > y->time.next)
- return 1;
-
- return 0;
+ return CMP(x->time.next, y->time.next);
}
static usec_t time_event_source_latest(const sd_event_source *s) {
@@ -418,12 +403,7 @@ static int latest_time_prioq_compare(const void *a, const void *b) {
return 1;
/* Order by time */
- if (time_event_source_latest(x) < time_event_source_latest(y))
- return -1;
- if (time_event_source_latest(x) > time_event_source_latest(y))
- return 1;
-
- return 0;
+ return CMP(time_event_source_latest(x), time_event_source_latest(y));
}
static int exit_prioq_compare(const void *a, const void *b) {
@@ -439,12 +419,7 @@ static int exit_prioq_compare(const void *a, const void *b) {
return 1;
/* Lower priority values first */
- if (x->priority < y->priority)
- return -1;
- if (x->priority > y->priority)
- return 1;
-
- return 0;
+ return CMP(x->priority, y->priority);
}
static void free_clock_data(struct clock_data *d) {
@@ -1590,21 +1565,16 @@ static int event_make_inotify_data(
static int inode_data_compare(const void *a, const void *b) {
const struct inode_data *x = a, *y = b;
+ int r;
assert(x);
assert(y);
- if (x->dev < y->dev)
- return -1;
- if (x->dev > y->dev)
- return 1;
-
- if (x->ino < y->ino)
- return -1;
- if (x->ino > y->ino)
- return 1;
+ r = CMP(x->dev, y->dev);
+ if (r != 0)
+ return r;
- return 0;
+ return CMP(x->ino, y->ino);
}
static void inode_data_hash_func(const void *p, struct siphash *state) {
diff --git a/src/systemd/src/systemd/sd-event.h b/src/systemd/src/systemd/sd-event.h
index eb35b83431..c38eb84beb 100644
--- a/src/systemd/src/systemd/sd-event.h
+++ b/src/systemd/src/systemd/sd-event.h
@@ -33,7 +33,8 @@
- Supports event source prioritization
- Scales better with a large number of time events because it does not require one timerfd each
- Automatically tries to coalesce timer events system-wide
- - Handles signals and child PIDs
+ - Handles signals, child PIDs, inotify events
+ - Supports systemd-style automatic watchdog event generation
*/
_SD_BEGIN_DECLARATIONS;