summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2016-08-11 10:51:49 +0200
committerThomas Haller <thaller@redhat.com>2016-08-11 12:50:51 +0200
commitc8ff87803944f8e16137328b5440b7bb87aa297f (patch)
tree009eba8bce9e2127816f3d649655fe0f156b43b3
parent21e3aa91d85cd5eab7d35d667bb0ec0277102818 (diff)
downloadNetworkManager-c8ff87803944f8e16137328b5440b7bb87aa297f.tar.gz
systemd: update code from upstream
This is a direct dump from systemd git on 2016-08-11, git commit 29df65f913ec7d360637ef1703ec284bb1fa6821. ====== SYSTEMD_DIR=../systemd COMMIT=29df65f913ec7d360637ef1703ec284bb1fa6821 ( cd "$SYSTEMD_DIR" git checkout "$COMMIT" git reset --hard git clean -fdx ) git ls-files :/src/systemd/src/ | xargs -d '\n' rm -f nm_copy_sd() { mkdir -p "./src/systemd/$(dirname "$1")" cp "$SYSTEMD_DIR/$1" "./src/systemd/$1" } nm_copy_sd "src/basic/alloc-util.c" nm_copy_sd "src/basic/alloc-util.h" nm_copy_sd "src/basic/async.h" nm_copy_sd "src/basic/escape.c" nm_copy_sd "src/basic/escape.h" nm_copy_sd "src/basic/ether-addr-util.c" nm_copy_sd "src/basic/ether-addr-util.h" nm_copy_sd "src/basic/extract-word.c" nm_copy_sd "src/basic/extract-word.h" nm_copy_sd "src/basic/fileio.c" nm_copy_sd "src/basic/fileio.h" nm_copy_sd "src/basic/fd-util.c" nm_copy_sd "src/basic/fd-util.h" nm_copy_sd "src/basic/fs-util.c" nm_copy_sd "src/basic/fs-util.h" nm_copy_sd "src/basic/hash-funcs.c" nm_copy_sd "src/basic/hash-funcs.h" nm_copy_sd "src/basic/hashmap.c" nm_copy_sd "src/basic/hashmap.h" nm_copy_sd "src/basic/hexdecoct.c" nm_copy_sd "src/basic/hexdecoct.h" nm_copy_sd "src/basic/hostname-util.c" nm_copy_sd "src/basic/hostname-util.h" nm_copy_sd "src/basic/in-addr-util.c" nm_copy_sd "src/basic/in-addr-util.h" nm_copy_sd "src/basic/io-util.c" nm_copy_sd "src/basic/io-util.h" nm_copy_sd "src/basic/list.h" nm_copy_sd "src/basic/log.h" nm_copy_sd "src/basic/macro.h" nm_copy_sd "src/basic/mempool.h" nm_copy_sd "src/basic/mempool.c" nm_copy_sd "src/basic/parse-util.c" nm_copy_sd "src/basic/parse-util.h" nm_copy_sd "src/basic/path-util.c" nm_copy_sd "src/basic/path-util.h" nm_copy_sd "src/basic/prioq.h" nm_copy_sd "src/basic/prioq.c" nm_copy_sd "src/basic/random-util.c" nm_copy_sd "src/basic/random-util.h" nm_copy_sd "src/basic/refcnt.h" nm_copy_sd "src/basic/set.h" nm_copy_sd "src/basic/signal-util.h" nm_copy_sd "src/basic/siphash24.c" nm_copy_sd "src/basic/siphash24.h" nm_copy_sd "src/basic/socket-util.c" nm_copy_sd "src/basic/socket-util.h" nm_copy_sd "src/basic/sparse-endian.h" nm_copy_sd "src/basic/stdio-util.h" nm_copy_sd "src/basic/string-table.c" nm_copy_sd "src/basic/string-table.h" nm_copy_sd "src/basic/string-util.c" nm_copy_sd "src/basic/string-util.h" nm_copy_sd "src/basic/strv.c" nm_copy_sd "src/basic/strv.h" nm_copy_sd "src/basic/time-util.c" nm_copy_sd "src/basic/time-util.h" nm_copy_sd "src/basic/umask-util.h" nm_copy_sd "src/basic/unaligned.h" nm_copy_sd "src/basic/utf8.c" nm_copy_sd "src/basic/utf8.h" nm_copy_sd "src/basic/util.c" nm_copy_sd "src/basic/util.h" nm_copy_sd "src/libsystemd-network/arp-util.c" nm_copy_sd "src/libsystemd-network/arp-util.h" nm_copy_sd "src/libsystemd-network/dhcp6-internal.h" nm_copy_sd "src/libsystemd-network/dhcp6-lease-internal.h" nm_copy_sd "src/libsystemd-network/dhcp6-network.c" nm_copy_sd "src/libsystemd-network/dhcp6-option.c" nm_copy_sd "src/libsystemd-network/dhcp6-protocol.h" nm_copy_sd "src/libsystemd-network/dhcp-identifier.c" nm_copy_sd "src/libsystemd-network/dhcp-identifier.h" nm_copy_sd "src/libsystemd-network/dhcp-internal.h" nm_copy_sd "src/libsystemd-network/dhcp-lease-internal.h" nm_copy_sd "src/libsystemd-network/dhcp-network.c" nm_copy_sd "src/libsystemd-network/dhcp-option.c" nm_copy_sd "src/libsystemd-network/dhcp-packet.c" nm_copy_sd "src/libsystemd-network/dhcp-protocol.h" nm_copy_sd "src/libsystemd-network/lldp-internal.h" nm_copy_sd "src/libsystemd-network/lldp-neighbor.c" nm_copy_sd "src/libsystemd-network/lldp-neighbor.h" nm_copy_sd "src/libsystemd-network/lldp-network.c" nm_copy_sd "src/libsystemd-network/lldp-network.h" nm_copy_sd "src/libsystemd-network/network-internal.c" nm_copy_sd "src/libsystemd-network/network-internal.h" nm_copy_sd "src/libsystemd-network/sd-dhcp6-client.c" nm_copy_sd "src/libsystemd-network/sd-dhcp6-lease.c" nm_copy_sd "src/libsystemd-network/sd-dhcp-client.c" nm_copy_sd "src/libsystemd-network/sd-dhcp-lease.c" nm_copy_sd "src/libsystemd-network/sd-ipv4ll.c" nm_copy_sd "src/libsystemd-network/sd-ipv4acd.c" nm_copy_sd "src/libsystemd-network/sd-lldp.c" nm_copy_sd "src/libsystemd/sd-event/sd-event.c" nm_copy_sd "src/libsystemd/sd-id128/id128-util.h" nm_copy_sd "src/libsystemd/sd-id128/sd-id128.c" nm_copy_sd "src/shared/dns-domain.c" nm_copy_sd "src/shared/dns-domain.h" nm_copy_sd "src/systemd/_sd-common.h" nm_copy_sd "src/systemd/sd-dhcp6-client.h" nm_copy_sd "src/systemd/sd-dhcp6-lease.h" nm_copy_sd "src/systemd/sd-dhcp-client.h" nm_copy_sd "src/systemd/sd-dhcp-lease.h" nm_copy_sd "src/systemd/sd-event.h" nm_copy_sd "src/systemd/sd-ndisc.h" nm_copy_sd "src/systemd/sd-id128.h" nm_copy_sd "src/systemd/sd-ipv4acd.h" nm_copy_sd "src/systemd/sd-ipv4ll.h" nm_copy_sd "src/systemd/sd-lldp.h"
-rw-r--r--src/systemd/src/basic/fd-util.c6
-rw-r--r--src/systemd/src/basic/fd-util.h1
-rw-r--r--src/systemd/src/basic/fileio.c84
-rw-r--r--src/systemd/src/basic/fileio.h2
-rw-r--r--src/systemd/src/basic/fs-util.c89
-rw-r--r--src/systemd/src/basic/fs-util.h3
-rw-r--r--src/systemd/src/basic/parse-util.c27
-rw-r--r--src/systemd/src/basic/parse-util.h3
-rw-r--r--src/systemd/src/basic/set.h8
-rw-r--r--src/systemd/src/basic/socket-util.c14
-rw-r--r--src/systemd/src/basic/socket-util.h2
-rw-r--r--src/systemd/src/basic/string-util.c45
-rw-r--r--src/systemd/src/basic/string-util.h3
-rw-r--r--src/systemd/src/basic/strv.c34
-rw-r--r--src/systemd/src/basic/time-util.c146
-rw-r--r--src/systemd/src/basic/time-util.h4
-rw-r--r--src/systemd/src/basic/util.c96
-rw-r--r--src/systemd/src/basic/util.h9
-rw-r--r--src/systemd/src/libsystemd-network/lldp-neighbor.c2
-rw-r--r--src/systemd/src/libsystemd-network/network-internal.c8
-rw-r--r--src/systemd/src/libsystemd/sd-event/sd-event.c14
-rw-r--r--src/systemd/src/libsystemd/sd-id128/id128-util.h45
-rw-r--r--src/systemd/src/libsystemd/sd-id128/sd-id128.c118
-rw-r--r--src/systemd/src/systemd/sd-event.h1
24 files changed, 557 insertions, 207 deletions
diff --git a/src/systemd/src/basic/fd-util.c b/src/systemd/src/basic/fd-util.c
index 8b466cff15..5c820332a5 100644
--- a/src/systemd/src/basic/fd-util.c
+++ b/src/systemd/src/basic/fd-util.c
@@ -186,6 +186,12 @@ int fd_cloexec(int fd, bool cloexec) {
return 0;
}
+void stdio_unset_cloexec(void) {
+ fd_cloexec(STDIN_FILENO, false);
+ fd_cloexec(STDOUT_FILENO, false);
+ fd_cloexec(STDERR_FILENO, false);
+}
+
_pure_ static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
unsigned i;
diff --git a/src/systemd/src/basic/fd-util.h b/src/systemd/src/basic/fd-util.h
index b86e41698a..34b98d4aec 100644
--- a/src/systemd/src/basic/fd-util.h
+++ b/src/systemd/src/basic/fd-util.h
@@ -63,6 +63,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DIR*, closedir);
int fd_nonblock(int fd, bool nonblock);
int fd_cloexec(int fd, bool cloexec);
+void stdio_unset_cloexec(void);
int close_all_fds(const int except[], unsigned n_except);
diff --git a/src/systemd/src/basic/fileio.c b/src/systemd/src/basic/fileio.c
index 29f5374222..d642f3daea 100644
--- a/src/systemd/src/basic/fileio.c
+++ b/src/systemd/src/basic/fileio.c
@@ -47,6 +47,8 @@
#include "umask-util.h"
#include "utf8.h"
+#define READ_FULL_BYTES_MAX (4U*1024U*1024U)
+
int write_string_stream(FILE *f, const char *line, bool enforce_newline) {
assert(f);
@@ -230,7 +232,7 @@ int read_full_stream(FILE *f, char **contents, size_t *size) {
if (S_ISREG(st.st_mode)) {
/* Safety check */
- if (st.st_size > 4*1024*1024)
+ if (st.st_size > READ_FULL_BYTES_MAX)
return -E2BIG;
/* Start with the right file size, but be prepared for
@@ -245,26 +247,31 @@ int read_full_stream(FILE *f, char **contents, size_t *size) {
char *t;
size_t k;
- t = realloc(buf, n+1);
+ t = realloc(buf, n + 1);
if (!t)
return -ENOMEM;
buf = t;
k = fread(buf + l, 1, n - l, f);
+ if (k > 0)
+ l += k;
- if (k <= 0) {
- if (ferror(f))
- return -errno;
+ if (ferror(f))
+ return -errno;
+ if (feof(f))
break;
- }
- l += k;
- n *= 2;
+ /* We aren't expecting fread() to return a short read outside
+ * of (error && eof), assert buffer is full and enlarge buffer.
+ */
+ assert(l == n);
/* Safety check */
- if (n > 4*1024*1024)
+ if (n >= READ_FULL_BYTES_MAX)
return -E2BIG;
+
+ n = MIN(n * 2, READ_FULL_BYTES_MAX);
}
buf[l] = 0;
@@ -1067,7 +1074,7 @@ int fflush_and_check(FILE *f) {
return 0;
}
-/* This is much like like mkostemp() but is subject to umask(). */
+/* This is much like mkostemp() but is subject to umask(). */
int mkostemp_safe(char *pattern, int flags) {
_cleanup_umask_ mode_t u = 0;
int fd;
@@ -1161,8 +1168,8 @@ int tempfn_random_child(const char *p, const char *extra, char **ret) {
char *t, *x;
uint64_t u;
unsigned i;
+ int r;
- assert(p);
assert(ret);
/* Turns this:
@@ -1171,6 +1178,12 @@ int tempfn_random_child(const char *p, const char *extra, char **ret) {
* /foo/bar/waldo/.#<extra>3c2b6219aa75d7d0
*/
+ if (!p) {
+ r = tmp_dir(&p);
+ if (r < 0)
+ return r;
+ }
+
if (!extra)
extra = "";
@@ -1257,9 +1270,13 @@ int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space)
int open_tmpfile_unlinkable(const char *directory, int flags) {
char *p;
- int fd;
+ int fd, r;
- assert(directory);
+ if (!directory) {
+ r = tmp_dir(&directory);
+ if (r < 0)
+ return r;
+ }
/* Returns an unlinked temporary file that cannot be linked into the file system anymore */
@@ -1354,3 +1371,44 @@ int link_tmpfile(int fd, const char *path, const char *target) {
return 0;
}
+
+int read_nul_string(FILE *f, char **ret) {
+ _cleanup_free_ char *x = NULL;
+ size_t allocated = 0, n = 0;
+
+ assert(f);
+ assert(ret);
+
+ /* Reads a NUL-terminated string from the specified file. */
+
+ for (;;) {
+ int c;
+
+ if (!GREEDY_REALLOC(x, allocated, n+2))
+ return -ENOMEM;
+
+ c = fgetc(f);
+ if (c == 0) /* Terminate at NUL byte */
+ break;
+ if (c == EOF) {
+ if (ferror(f))
+ return -errno;
+ break; /* Terminate at EOF */
+ }
+
+ x[n++] = (char) c;
+ }
+
+ if (x)
+ x[n] = 0;
+ else {
+ x = new0(char, 1);
+ if (!x)
+ return -ENOMEM;
+ }
+
+ *ret = x;
+ x = NULL;
+
+ return 0;
+}
diff --git a/src/systemd/src/basic/fileio.h b/src/systemd/src/basic/fileio.h
index 58dbc80c24..9ac497d9eb 100644
--- a/src/systemd/src/basic/fileio.h
+++ b/src/systemd/src/basic/fileio.h
@@ -86,3 +86,5 @@ int open_tmpfile_unlinkable(const char *directory, int flags);
int open_tmpfile_linkable(const char *target, int flags, char **ret_path);
int link_tmpfile(int fd, const char *path, const char *target);
+
+int read_nul_string(FILE *f, char **ret);
diff --git a/src/systemd/src/basic/fs-util.c b/src/systemd/src/basic/fs-util.c
index e24e7036f7..ce87257bc1 100644
--- a/src/systemd/src/basic/fs-util.c
+++ b/src/systemd/src/basic/fs-util.c
@@ -38,6 +38,7 @@
#include "mkdir.h"
#include "parse-util.h"
#include "path-util.h"
+#include "stat-util.h"
#include "stdio-util.h"
#include "string-util.h"
#include "strv.h"
@@ -495,6 +496,94 @@ int get_files_in_directory(const char *path, char ***list) {
return n;
}
+static int getenv_tmp_dir(const char **ret_path) {
+ const char *n;
+ int r, ret = 0;
+
+ assert(ret_path);
+
+ /* We use the same order of environment variables python uses in tempfile.gettempdir():
+ * https://docs.python.org/3/library/tempfile.html#tempfile.gettempdir */
+ FOREACH_STRING(n, "TMPDIR", "TEMP", "TMP") {
+ const char *e;
+
+ e = secure_getenv(n);
+ if (!e)
+ continue;
+ if (!path_is_absolute(e)) {
+ r = -ENOTDIR;
+ goto next;
+ }
+ if (!path_is_safe(e)) {
+ r = -EPERM;
+ goto next;
+ }
+
+ r = is_dir(e, true);
+ if (r < 0)
+ goto next;
+ if (r == 0) {
+ r = -ENOTDIR;
+ goto next;
+ }
+
+ *ret_path = e;
+ return 1;
+
+ next:
+ /* Remember first error, to make this more debuggable */
+ if (ret >= 0)
+ ret = r;
+ }
+
+ if (ret < 0)
+ return ret;
+
+ *ret_path = NULL;
+ return ret;
+}
+
+static int tmp_dir_internal(const char *def, const char **ret) {
+ const char *e;
+ int r, k;
+
+ assert(def);
+ assert(ret);
+
+ r = getenv_tmp_dir(&e);
+ if (r > 0) {
+ *ret = e;
+ return 0;
+ }
+
+ k = is_dir(def, true);
+ if (k == 0)
+ k = -ENOTDIR;
+ if (k < 0)
+ return r < 0 ? r : k;
+
+ *ret = def;
+ return 0;
+}
+
+int var_tmp_dir(const char **ret) {
+
+ /* Returns the location for "larger" temporary files, that is backed by physical storage if available, and thus
+ * even might survive a boot: /var/tmp. If $TMPDIR (or related environment variables) are set, its value is
+ * returned preferably however. Note that both this function and tmp_dir() below are affected by $TMPDIR,
+ * making it a variable that overrides all temporary file storage locations. */
+
+ return tmp_dir_internal("/var/tmp", ret);
+}
+
+int tmp_dir(const char **ret) {
+
+ /* Similar to var_tmp_dir() above, but returns the location for "smaller" temporary files, which is usually
+ * backed by an in-memory file system: /tmp. */
+
+ return tmp_dir_internal("/tmp", ret);
+}
+
int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
char path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
int r;
diff --git a/src/systemd/src/basic/fs-util.h b/src/systemd/src/basic/fs-util.h
index 517b599d6f..2c3b9a1c74 100644
--- a/src/systemd/src/basic/fs-util.h
+++ b/src/systemd/src/basic/fs-util.h
@@ -61,6 +61,9 @@ int mkfifo_atomic(const char *path, mode_t mode);
int get_files_in_directory(const char *path, char ***list);
+int tmp_dir(const char **ret);
+int var_tmp_dir(const char **ret);
+
#define INOTIFY_EVENT_MAX (sizeof(struct inotify_event) + NAME_MAX + 1)
#define FOREACH_INOTIFY_EVENT(e, buffer, sz) \
diff --git a/src/systemd/src/basic/parse-util.c b/src/systemd/src/basic/parse-util.c
index 503a895731..c98815b9bc 100644
--- a/src/systemd/src/basic/parse-util.c
+++ b/src/systemd/src/basic/parse-util.c
@@ -29,6 +29,7 @@
#include "extract-word.h"
#include "macro.h"
#include "parse-util.h"
+#include "process-util.h"
#include "string-util.h"
int parse_boolean(const char *v) {
@@ -533,7 +534,7 @@ int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) {
return 0;
}
-int parse_percent(const char *p) {
+int parse_percent_unbounded(const char *p) {
const char *pc, *n;
unsigned v;
int r;
@@ -546,8 +547,30 @@ int parse_percent(const char *p) {
r = safe_atou(n, &v);
if (r < 0)
return r;
+
+ return (int) v;
+}
+
+int parse_percent(const char *p) {
+ int v;
+
+ v = parse_percent_unbounded(p);
if (v > 100)
return -ERANGE;
- return (int) v;
+ return v;
+}
+
+int parse_nice(const char *p, int *ret) {
+ int n, r;
+
+ r = safe_atoi(p, &n);
+ if (r < 0)
+ return r;
+
+ if (!nice_is_valid(n))
+ return -ERANGE;
+
+ *ret = n;
+ return 0;
}
diff --git a/src/systemd/src/basic/parse-util.h b/src/systemd/src/basic/parse-util.h
index 73441bb6fd..461e1cd4d8 100644
--- a/src/systemd/src/basic/parse-util.h
+++ b/src/systemd/src/basic/parse-util.h
@@ -106,4 +106,7 @@ int safe_atod(const char *s, double *ret_d);
int parse_fractional_part_u(const char **s, size_t digits, unsigned *res);
+int parse_percent_unbounded(const char *p);
int parse_percent(const char *p);
+
+int parse_nice(const char *p, int *ret);
diff --git a/src/systemd/src/basic/set.h b/src/systemd/src/basic/set.h
index 12f64a8c57..a5f8beb0c4 100644
--- a/src/systemd/src/basic/set.h
+++ b/src/systemd/src/basic/set.h
@@ -23,8 +23,8 @@
#include "hashmap.h"
#include "macro.h"
-Set *internal_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
-#define set_new(ops) internal_set_new(ops HASHMAP_DEBUG_SRC_ARGS)
+Set *internal_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
+#define set_new(ops) internal_set_new(ops HASHMAP_DEBUG_SRC_ARGS)
static inline Set *set_free(Set *s) {
internal_hashmap_free(HASHMAP_BASE(s));
@@ -42,8 +42,8 @@ static inline Set *set_copy(Set *s) {
return (Set*) internal_hashmap_copy(HASHMAP_BASE(s));
}
-int internal_set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
-#define set_ensure_allocated(h, ops) internal_set_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS)
+int internal_set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
+#define set_ensure_allocated(h, ops) internal_set_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS)
int set_put(Set *s, const void *key);
/* no set_update */
diff --git a/src/systemd/src/basic/socket-util.c b/src/systemd/src/basic/socket-util.c
index 385c3e4df3..6093e47172 100644
--- a/src/systemd/src/basic/socket-util.c
+++ b/src/systemd/src/basic/socket-util.c
@@ -1046,3 +1046,17 @@ int flush_accept(int fd) {
close(cfd);
}
}
+
+struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t length) {
+ struct cmsghdr *cmsg;
+
+ assert(mh);
+
+ CMSG_FOREACH(cmsg, mh)
+ if (cmsg->cmsg_level == level &&
+ cmsg->cmsg_type == type &&
+ (length == (socklen_t) -1 || length == cmsg->cmsg_len))
+ return cmsg;
+
+ return NULL;
+}
diff --git a/src/systemd/src/basic/socket-util.h b/src/systemd/src/basic/socket-util.h
index e9230e4a9f..2536b085f9 100644
--- a/src/systemd/src/basic/socket-util.h
+++ b/src/systemd/src/basic/socket-util.h
@@ -142,6 +142,8 @@ int flush_accept(int fd);
#define CMSG_FOREACH(cmsg, mh) \
for ((cmsg) = CMSG_FIRSTHDR(mh); (cmsg); (cmsg) = CMSG_NXTHDR((mh), (cmsg)))
+struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t length);
+
/* Covers only file system and abstract AF_UNIX socket addresses, but not unnamed socket addresses. */
#define SOCKADDR_UN_LEN(sa) \
({ \
diff --git a/src/systemd/src/basic/string-util.c b/src/systemd/src/basic/string-util.c
index 293a15f9c0..5d4510e1b3 100644
--- a/src/systemd/src/basic/string-util.c
+++ b/src/systemd/src/basic/string-util.c
@@ -22,6 +22,7 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include "alloc-util.h"
#include "gunicode.h"
@@ -323,6 +324,14 @@ char ascii_tolower(char x) {
return x;
}
+char ascii_toupper(char x) {
+
+ if (x >= 'a' && x <= 'z')
+ return x - 'a' + 'A';
+
+ return x;
+}
+
char *ascii_strlower(char *t) {
char *p;
@@ -334,6 +343,17 @@ char *ascii_strlower(char *t) {
return t;
}
+char *ascii_strupper(char *t) {
+ char *p;
+
+ assert(t);
+
+ for (p = t; *p; p++)
+ *p = ascii_toupper(*p);
+
+ return t;
+}
+
char *ascii_strlower_n(char *t, size_t n) {
size_t i;
@@ -803,25 +823,20 @@ int free_and_strdup(char **p, const char *s) {
return 1;
}
-#pragma GCC push_options
-#pragma GCC optimize("O0")
+/*
+ * Pointer to memset is volatile so that compiler must de-reference
+ * the pointer and can't assume that it points to any function in
+ * particular (such as memset, which it then might further "optimize")
+ * This approach is inspired by openssl's crypto/mem_clr.c.
+ */
+typedef void *(*memset_t)(void *,int,size_t);
-void* memory_erase(void *p, size_t l) {
- volatile uint8_t* x = (volatile uint8_t*) p;
+static volatile memset_t memset_func = memset;
- /* This basically does what memset() does, but hopefully isn't
- * optimized away by the compiler. One of those days, when
- * glibc learns memset_s() we should replace this call by
- * memset_s(), but until then this has to do. */
-
- for (; l > 0; l--)
- *(x++) = 'x';
-
- return p;
+void* memory_erase(void *p, size_t l) {
+ return memset_func(p, 'x', l);
}
-#pragma GCC pop_options
-
char* string_erase(char *x) {
if (!x)
diff --git a/src/systemd/src/basic/string-util.h b/src/systemd/src/basic/string-util.h
index 1209e1e2e1..b75aba63c2 100644
--- a/src/systemd/src/basic/string-util.h
+++ b/src/systemd/src/basic/string-util.h
@@ -137,6 +137,9 @@ char ascii_tolower(char x);
char *ascii_strlower(char *s);
char *ascii_strlower_n(char *s, size_t n);
+char ascii_toupper(char x);
+char *ascii_strupper(char *s);
+
int ascii_strcasecmp_n(const char *a, const char *b, size_t n);
int ascii_strcasecmp_nn(const char *a, size_t n, const char *b, size_t m);
diff --git a/src/systemd/src/basic/strv.c b/src/systemd/src/basic/strv.c
index 53298268f4..34e464d253 100644
--- a/src/systemd/src/basic/strv.c
+++ b/src/systemd/src/basic/strv.c
@@ -638,6 +638,17 @@ char **strv_remove(char **l, const char *s) {
}
char **strv_parse_nulstr(const char *s, size_t l) {
+ /* l is the length of the input data, which will be split at NULs into
+ * elements of the resulting strv. Hence, the number of items in the resulting strv
+ * will be equal to one plus the number of NUL bytes in the l bytes starting at s,
+ * unless s[l-1] is NUL, in which case the final empty string is not stored in
+ * the resulting strv, and length is equal to the number of NUL bytes.
+ *
+ * Note that contrary to a normal nulstr which cannot contain empty strings, because
+ * the input data is terminated by any two consequent NUL bytes, this parser accepts
+ * empty strings in s.
+ */
+
const char *p;
unsigned c = 0, i = 0;
char **v;
@@ -700,6 +711,13 @@ char **strv_split_nulstr(const char *s) {
}
int strv_make_nulstr(char **l, char **p, size_t *q) {
+ /* A valid nulstr with two NULs at the end will be created, but
+ * q will be the length without the two trailing NULs. Thus the output
+ * string is a valid nulstr and can be iterated over using NULSTR_FOREACH,
+ * and can also be parsed by strv_parse_nulstr as long as the length
+ * is provided separately.
+ */
+
size_t n_allocated = 0, n = 0;
_cleanup_free_ char *m = NULL;
char **i;
@@ -712,7 +730,7 @@ int strv_make_nulstr(char **l, char **p, size_t *q) {
z = strlen(*i);
- if (!GREEDY_REALLOC(m, n_allocated, n + z + 1))
+ if (!GREEDY_REALLOC(m, n_allocated, n + z + 2))
return -ENOMEM;
memcpy(m + n, *i, z + 1);
@@ -723,11 +741,14 @@ int strv_make_nulstr(char **l, char **p, size_t *q) {
m = new0(char, 1);
if (!m)
return -ENOMEM;
- n = 0;
- }
+ n = 1;
+ } else
+ /* make sure there is a second extra NUL at the end of resulting nulstr */
+ m[n] = '\0';
+ assert(n > 0);
*p = m;
- *q = n;
+ *q = n - 1;
m = NULL;
@@ -803,9 +824,8 @@ char **strv_reverse(char **l) {
if (n <= 1)
return l;
- for (i = 0; i < n / 2; i++) {
+ for (i = 0; i < n / 2; i++)
SWAP_TWO(l[i], l[n-1-i]);
- }
return l;
}
@@ -876,7 +896,7 @@ int strv_extend_n(char ***l, const char *value, size_t n) {
if (n == 0)
return 0;
- /* Adds the value value n times to l */
+ /* Adds the value n times to l */
k = strv_length(*l);
diff --git a/src/systemd/src/basic/time-util.c b/src/systemd/src/basic/time-util.c
index 24e681bf85..0ef1f6393e 100644
--- a/src/systemd/src/basic/time-util.c
+++ b/src/systemd/src/basic/time-util.c
@@ -254,32 +254,95 @@ struct timeval *timeval_store(struct timeval *tv, usec_t u) {
return tv;
}
-static char *format_timestamp_internal(char *buf, size_t l, usec_t t,
- bool utc, bool us) {
+static char *format_timestamp_internal(
+ char *buf,
+ size_t l,
+ usec_t t,
+ bool utc,
+ bool us) {
+
+ /* The weekdays in non-localized (English) form. We use this instead of the localized form, so that our
+ * generated timestamps may be parsed with parse_timestamp(), and always read the same. */
+ static const char * const weekdays[] = {
+ [0] = "Sun",
+ [1] = "Mon",
+ [2] = "Tue",
+ [3] = "Wed",
+ [4] = "Thu",
+ [5] = "Fri",
+ [6] = "Sat",
+ };
+
struct tm tm;
time_t sec;
- int k;
+ size_t n;
assert(buf);
- assert(l > 0);
+ if (l <
+ 3 + /* week day */
+ 1 + 10 + /* space and date */
+ 1 + 8 + /* space and time */
+ (us ? 1 + 6 : 0) + /* "." and microsecond part */
+ 1 + 1 + /* space and shortest possible zone */
+ 1)
+ return NULL; /* Not enough space even for the shortest form. */
if (t <= 0 || t == USEC_INFINITY)
+ return NULL; /* Timestamp is unset */
+
+ sec = (time_t) (t / USEC_PER_SEC); /* Round down */
+ if ((usec_t) sec != (t / USEC_PER_SEC))
+ return NULL; /* overflow? */
+
+ if (!localtime_or_gmtime_r(&sec, &tm, utc))
return NULL;
- sec = (time_t) (t / USEC_PER_SEC);
- localtime_or_gmtime_r(&sec, &tm, utc);
+ /* Start with the week day */
+ assert((size_t) tm.tm_wday < ELEMENTSOF(weekdays));
+ memcpy(buf, weekdays[tm.tm_wday], 4);
- if (us)
- k = strftime(buf, l, "%a %Y-%m-%d %H:%M:%S", &tm);
- else
- k = strftime(buf, l, "%a %Y-%m-%d %H:%M:%S %Z", &tm);
+ /* Add the main components */
+ if (strftime(buf + 3, l - 3, " %Y-%m-%d %H:%M:%S", &tm) <= 0)
+ return NULL; /* Doesn't fit */
- if (k <= 0)
- return NULL;
+ /* Append the microseconds part, if that's requested */
if (us) {
- snprintf(buf + strlen(buf), l - strlen(buf), ".%06llu", (unsigned long long) (t % USEC_PER_SEC));
- if (strftime(buf + strlen(buf), l - strlen(buf), " %Z", &tm) <= 0)
- return NULL;
+ n = strlen(buf);
+ if (n + 8 > l)
+ return NULL; /* Microseconds part doesn't fit. */
+
+ sprintf(buf + n, ".%06llu", (unsigned long long) (t % USEC_PER_SEC));
+ }
+
+ /* Append the timezone */
+ n = strlen(buf);
+ if (utc) {
+ /* If this is UTC then let's explicitly use the "UTC" string here, because gmtime_r() normally uses the
+ * obsolete "GMT" instead. */
+ if (n + 5 > l)
+ return NULL; /* "UTC" doesn't fit. */
+
+ strcpy(buf + n, " UTC");
+
+ } else if (!isempty(tm.tm_zone)) {
+ size_t tn;
+
+ /* An explicit timezone is specified, let's use it, if it fits */
+ tn = strlen(tm.tm_zone);
+ if (n + 1 + tn + 1 > l) {
+ /* The full time zone does not fit in. Yuck. */
+
+ if (n + 1 + _POSIX_TZNAME_MAX + 1 > l)
+ return NULL; /* Not even enough space for the POSIX minimum (of 6)? In that case, complain that it doesn't fit */
+
+ /* So the time zone doesn't fit in fully, but the caller passed enough space for the POSIX
+ * minimum time zone length. In this case suppress the timezone entirely, in order not to dump
+ * an overly long, hard to read string on the user. This should be safe, because the user will
+ * assume the local timezone anyway if none is shown. And so does parse_timestamp(). */
+ } else {
+ buf[n++] = ' ';
+ strcpy(buf + n, tm.tm_zone);
+ }
}
return buf;
@@ -539,12 +602,11 @@ int parse_timestamp(const char *t, usec_t *usec) {
{ "Sat", 6 },
};
- const char *k;
- const char *utc;
+ const char *k, *utc, *tzn = NULL;
struct tm tm, copy;
time_t x;
usec_t x_usec, plus = 0, minus = 0, ret;
- int r, weekday = -1;
+ int r, weekday = -1, dst = -1;
unsigned i;
/*
@@ -609,15 +671,55 @@ int parse_timestamp(const char *t, usec_t *usec) {
goto finish;
}
+ /* See if the timestamp is suffixed with UTC */
utc = endswith_no_case(t, " UTC");
if (utc)
t = strndupa(t, utc - t);
+ else {
+ const char *e = NULL;
+ int j;
+
+ tzset();
+
+ /* See if the timestamp is suffixed by either the DST or non-DST local timezone. Note that we only
+ * support the local timezones here, nothing else. Not because we wouldn't want to, but simply because
+ * there are no nice APIs available to cover this. By accepting the local time zone strings, we make
+ * sure that all timestamps written by format_timestamp() can be parsed correctly, even though we don't
+ * support arbitrary timezone specifications. */
+
+ for (j = 0; j <= 1; j++) {
+
+ if (isempty(tzname[j]))
+ continue;
+
+ e = endswith_no_case(t, tzname[j]);
+ if (!e)
+ continue;
+ if (e == t)
+ continue;
+ if (e[-1] != ' ')
+ continue;
+
+ break;
+ }
- x = ret / USEC_PER_SEC;
+ if (IN_SET(j, 0, 1)) {
+ /* Found one of the two timezones specified. */
+ t = strndupa(t, e - t - 1);
+ dst = j;
+ tzn = tzname[j];
+ }
+ }
+
+ x = (time_t) (ret / USEC_PER_SEC);
x_usec = 0;
- assert_se(localtime_or_gmtime_r(&x, &tm, utc));
- tm.tm_isdst = -1;
+ if (!localtime_or_gmtime_r(&x, &tm, utc))
+ return -EINVAL;
+
+ tm.tm_isdst = dst;
+ if (tzn)
+ tm.tm_zone = tzn;
if (streq(t, "today")) {
tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
@@ -634,7 +736,6 @@ int parse_timestamp(const char *t, usec_t *usec) {
goto from_tm;
}
-
for (i = 0; i < ELEMENTSOF(day_nr); i++) {
size_t skip;
@@ -727,7 +828,6 @@ parse_usec:
return -EINVAL;
x_usec = add;
-
}
from_tm:
diff --git a/src/systemd/src/basic/time-util.h b/src/systemd/src/basic/time-util.h
index 1b058f0e49..99be5ce6ee 100644
--- a/src/systemd/src/basic/time-util.h
+++ b/src/systemd/src/basic/time-util.h
@@ -68,7 +68,9 @@ typedef struct triple_timestamp {
#define USEC_PER_YEAR ((usec_t) (31557600ULL*USEC_PER_SEC))
#define NSEC_PER_YEAR ((nsec_t) (31557600ULL*NSEC_PER_SEC))
-#define FORMAT_TIMESTAMP_MAX ((4*4+1)+11+9+4+1) /* weekdays can be unicode */
+/* We assume a maximum timezone length of 6. TZNAME_MAX is not defined on Linux, but glibc internally initializes this
+ * to 6. Let's rely on that. */
+#define FORMAT_TIMESTAMP_MAX (3+1+10+1+8+1+6+1+6+1)
#define FORMAT_TIMESTAMP_WIDTH 28 /* when outputting, assume this width */
#define FORMAT_TIMESTAMP_RELATIVE_MAX 256
#define FORMAT_TIMESPAN_MAX 64
diff --git a/src/systemd/src/basic/util.c b/src/systemd/src/basic/util.c
index 09d16697b7..9d66d28eb7 100644
--- a/src/systemd/src/basic/util.c
+++ b/src/systemd/src/basic/util.c
@@ -581,47 +581,6 @@ int on_ac_power(void) {
return found_online || !found_offline;
}
-bool id128_is_valid(const char *s) {
- size_t i, l;
-
- l = strlen(s);
- if (l == 32) {
-
- /* Simple formatted 128bit hex string */
-
- for (i = 0; i < l; i++) {
- char c = s[i];
-
- if (!(c >= '0' && c <= '9') &&
- !(c >= 'a' && c <= 'z') &&
- !(c >= 'A' && c <= 'Z'))
- return false;
- }
-
- } else if (l == 36) {
-
- /* Formatted UUID */
-
- for (i = 0; i < l; i++) {
- char c = s[i];
-
- if ((i == 8 || i == 13 || i == 18 || i == 23)) {
- if (c != '-')
- return false;
- } else {
- if (!(c >= '0' && c <= '9') &&
- !(c >= 'a' && c <= 'z') &&
- !(c >= 'A' && c <= 'Z'))
- return false;
- }
- }
-
- } else
- return false;
-
- return true;
-}
-
int container_get_leader(const char *machine, pid_t *pid) {
_cleanup_free_ char *s = NULL, *class = NULL;
const char *p;
@@ -832,6 +791,61 @@ uint64_t physical_memory_scale(uint64_t v, uint64_t max) {
return r;
}
+uint64_t system_tasks_max(void) {
+
+#if SIZEOF_PID_T == 4
+#define TASKS_MAX ((uint64_t) (INT32_MAX-1))
+#elif SIZEOF_PID_T == 2
+#define TASKS_MAX ((uint64_t) (INT16_MAX-1))
+#else
+#error "Unknown pid_t size"
+#endif
+
+ _cleanup_free_ char *value = NULL, *root = NULL;
+ uint64_t a = TASKS_MAX, b = TASKS_MAX;
+
+ /* Determine the maximum number of tasks that may run on this system. We check three sources to determine this
+ * limit:
+ *
+ * a) the maximum value for the pid_t type
+ * b) the cgroups pids_max attribute for the system
+ * c) the kernel's configure maximum PID value
+ *
+ * And then pick the smallest of the three */
+
+ if (read_one_line_file("/proc/sys/kernel/pid_max", &value) >= 0)
+ (void) safe_atou64(value, &a);
+
+ if (cg_get_root_path(&root) >= 0) {
+ value = mfree(value);
+
+ if (cg_get_attribute("pids", root, "pids.max", &value) >= 0)
+ (void) safe_atou64(value, &b);
+ }
+
+ return MIN3(TASKS_MAX,
+ a <= 0 ? TASKS_MAX : a,
+ b <= 0 ? TASKS_MAX : b);
+}
+
+uint64_t system_tasks_max_scale(uint64_t v, uint64_t max) {
+ uint64_t t, m;
+
+ assert(max > 0);
+
+ /* Multiply the system's task value by the fraction v/max. Hence, if max==100 this calculates percentages
+ * relative to the system's maximum number of tasks. Returns UINT64_MAX on overflow. */
+
+ t = system_tasks_max();
+ assert(t > 0);
+
+ m = t * v;
+ if (m / t != v) /* overflow? */
+ return UINT64_MAX;
+
+ return m / max;
+}
+
int update_reboot_parameter_and_warn(const char *param) {
int r;
diff --git a/src/systemd/src/basic/util.h b/src/systemd/src/basic/util.h
index db105197e8..bb2fc318ef 100644
--- a/src/systemd/src/basic/util.h
+++ b/src/systemd/src/basic/util.h
@@ -61,6 +61,10 @@ static inline const char* one_zero(bool b) {
return b ? "1" : "0";
}
+static inline const char* enable_disable(bool b) {
+ return b ? "enable" : "disable";
+}
+
void execute_directories(const char* const* directories, usec_t timeout, char *argv[]);
bool plymouth_running(void);
@@ -176,8 +180,6 @@ static inline unsigned log2u_round_up(unsigned x) {
return log2u(x - 1) + 1;
}
-bool id128_is_valid(const char *s) _pure_;
-
int container_get_leader(const char *machine, pid_t *pid);
int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd);
@@ -186,6 +188,9 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int
uint64_t physical_memory(void);
uint64_t physical_memory_scale(uint64_t v, uint64_t max);
+uint64_t system_tasks_max(void);
+uint64_t system_tasks_max_scale(uint64_t v, uint64_t max);
+
int update_reboot_parameter_and_warn(const char *param);
int version(void);
diff --git a/src/systemd/src/libsystemd-network/lldp-neighbor.c b/src/systemd/src/libsystemd-network/lldp-neighbor.c
index 88f7e329b0..53e29377b3 100644
--- a/src/systemd/src/libsystemd-network/lldp-neighbor.c
+++ b/src/systemd/src/libsystemd-network/lldp-neighbor.c
@@ -197,7 +197,7 @@ int lldp_neighbor_parse(sd_lldp_neighbor *n) {
assert(n);
if (n->raw_size < sizeof(struct ether_header)) {
- log_lldp("Recieved truncated packet, ignoring.");
+ log_lldp("Received truncated packet, ignoring.");
return -EBADMSG;
}
diff --git a/src/systemd/src/libsystemd-network/network-internal.c b/src/systemd/src/libsystemd-network/network-internal.c
index ce30b7fc25..9d78b953fc 100644
--- a/src/systemd/src/libsystemd-network/network-internal.c
+++ b/src/systemd/src/libsystemd-network/network-internal.c
@@ -102,16 +102,16 @@ bool net_match_config(const struct ether_addr *match_mac,
const char *dev_type,
const char *dev_name) {
- if (match_host && !condition_test(match_host))
+ if (match_host && condition_test(match_host) <= 0)
return false;
- if (match_virt && !condition_test(match_virt))
+ if (match_virt && condition_test(match_virt) <= 0)
return false;
- if (match_kernel && !condition_test(match_kernel))
+ if (match_kernel && condition_test(match_kernel) <= 0)
return false;
- if (match_arch && !condition_test(match_arch))
+ if (match_arch && condition_test(match_arch) <= 0)
return false;
if (match_mac && (!dev_mac || memcmp(match_mac, dev_mac, ETH_ALEN)))
diff --git a/src/systemd/src/libsystemd/sd-event/sd-event.c b/src/systemd/src/libsystemd/sd-event/sd-event.c
index f364b54b50..9857f8b1fc 100644
--- a/src/systemd/src/libsystemd/sd-event/sd-event.c
+++ b/src/systemd/src/libsystemd/sd-event/sd-event.c
@@ -109,8 +109,8 @@ struct sd_event_source {
int64_t priority;
unsigned pending_index;
unsigned prepare_index;
- unsigned pending_iteration;
- unsigned prepare_iteration;
+ uint64_t pending_iteration;
+ uint64_t prepare_iteration;
LIST_FIELDS(sd_event_source, sources);
@@ -215,7 +215,7 @@ struct sd_event {
pid_t original_pid;
- unsigned iteration;
+ uint64_t iteration;
triple_timestamp timestamp;
int state;
@@ -2874,3 +2874,11 @@ _public_ int sd_event_get_watchdog(sd_event *e) {
return e->watchdog;
}
+
+_public_ int sd_event_get_iteration(sd_event *e, uint64_t *ret) {
+ assert_return(e, -EINVAL);
+ assert_return(!event_pid_changed(e), -ECHILD);
+
+ *ret = e->iteration;
+ return 0;
+}
diff --git a/src/systemd/src/libsystemd/sd-id128/id128-util.h b/src/systemd/src/libsystemd/sd-id128/id128-util.h
new file mode 100644
index 0000000000..3ba59acbca
--- /dev/null
+++ b/src/systemd/src/libsystemd/sd-id128/id128-util.h
@@ -0,0 +1,45 @@
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2016 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdbool.h>
+
+#include "sd-id128.h"
+#include "macro.h"
+
+char *id128_to_uuid_string(sd_id128_t id, char s[37]);
+
+/* Like SD_ID128_FORMAT_STR, but formats as UUID, not in plain format */
+#define ID128_UUID_FORMAT_STR "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
+
+bool id128_is_valid(const char *s) _pure_;
+
+typedef enum Id128Format {
+ ID128_ANY,
+ ID128_PLAIN, /* formatted as 32 hex chars as-is */
+ ID128_UUID, /* formatted as 36 character uuid string */
+ _ID128_FORMAT_MAX,
+} Id128Format;
+
+int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret);
+int id128_read(const char *p, Id128Format f, sd_id128_t *ret);
+
+int id128_write_fd(int fd, Id128Format f, sd_id128_t id, bool do_sync);
+int id128_write(const char *p, Id128Format f, sd_id128_t id, bool do_sync);
diff --git a/src/systemd/src/libsystemd/sd-id128/sd-id128.c b/src/systemd/src/libsystemd/sd-id128/sd-id128.c
index d9c0116f60..9f47d04e61 100644
--- a/src/systemd/src/libsystemd/sd-id128/sd-id128.c
+++ b/src/systemd/src/libsystemd/sd-id128/sd-id128.c
@@ -25,6 +25,7 @@
#include "fd-util.h"
#include "hexdecoct.h"
+#include "id128-util.h"
#include "io-util.h"
#include "macro.h"
#include "random-util.h"
@@ -51,7 +52,6 @@ _public_ int sd_id128_from_string(const char s[], sd_id128_t *ret) {
bool is_guid = false;
assert_return(s, -EINVAL);
- assert_return(ret, -EINVAL);
for (n = 0, i = 0; n < 16;) {
int a, b;
@@ -89,121 +89,57 @@ _public_ int sd_id128_from_string(const char s[], sd_id128_t *ret) {
if (s[i] != 0)
return -EINVAL;
- *ret = t;
+ if (ret)
+ *ret = t;
return 0;
}
-static sd_id128_t make_v4_uuid(sd_id128_t id) {
- /* Stolen from generate_random_uuid() of drivers/char/random.c
- * in the kernel sources */
-
- /* Set UUID version to 4 --- truly random generation */
- id.bytes[6] = (id.bytes[6] & 0x0F) | 0x40;
-
- /* Set the UUID variant to DCE */
- id.bytes[8] = (id.bytes[8] & 0x3F) | 0x80;
-
- return id;
-}
-
_public_ int sd_id128_get_machine(sd_id128_t *ret) {
- static thread_local sd_id128_t saved_machine_id;
- static thread_local bool saved_machine_id_valid = false;
- _cleanup_close_ int fd = -1;
- char buf[33];
- unsigned j;
- sd_id128_t t;
+ static thread_local sd_id128_t saved_machine_id = {};
int r;
assert_return(ret, -EINVAL);
- if (saved_machine_id_valid) {
- *ret = saved_machine_id;
- return 0;
- }
-
- fd = open("/etc/machine-id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (fd < 0)
- return -errno;
-
- r = loop_read_exact(fd, buf, 33, false);
- if (r < 0)
- return r;
- if (buf[32] !='\n')
- return -EIO;
-
- for (j = 0; j < 16; j++) {
- int a, b;
-
- a = unhexchar(buf[j*2]);
- b = unhexchar(buf[j*2+1]);
-
- if (a < 0 || b < 0)
- return -EIO;
+ if (sd_id128_is_null(saved_machine_id)) {
+ r = id128_read("/etc/machine-id", ID128_PLAIN, &saved_machine_id);
+ if (r < 0)
+ return r;
- t.bytes[j] = a << 4 | b;
+ if (sd_id128_is_null(saved_machine_id))
+ return -EINVAL;
}
- saved_machine_id = t;
- saved_machine_id_valid = true;
-
- *ret = t;
+ *ret = saved_machine_id;
return 0;
}
_public_ int sd_id128_get_boot(sd_id128_t *ret) {
- static thread_local sd_id128_t saved_boot_id;
- static thread_local bool saved_boot_id_valid = false;
- _cleanup_close_ int fd = -1;
- char buf[36];
- unsigned j;
- sd_id128_t t;
- char *p;
+ static thread_local sd_id128_t saved_boot_id = {};
int r;
assert_return(ret, -EINVAL);
- if (saved_boot_id_valid) {
- *ret = saved_boot_id;
- return 0;
+ if (sd_id128_is_null(saved_boot_id)) {
+ r = id128_read("/proc/sys/kernel/random/boot_id", ID128_UUID, &saved_boot_id);
+ if (r < 0)
+ return r;
}
- fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (fd < 0)
- return -errno;
-
- r = loop_read_exact(fd, buf, 36, false);
- if (r < 0)
- return r;
-
- for (j = 0, p = buf; j < 16; j++) {
- int a, b;
-
- if (p >= buf + 35)
- return -EIO;
-
- if (*p == '-') {
- p++;
- if (p >= buf + 35)
- return -EIO;
- }
-
- a = unhexchar(p[0]);
- b = unhexchar(p[1]);
-
- if (a < 0 || b < 0)
- return -EIO;
+ *ret = saved_boot_id;
+ return 0;
+}
- t.bytes[j] = a << 4 | b;
+static sd_id128_t make_v4_uuid(sd_id128_t id) {
+ /* Stolen from generate_random_uuid() of drivers/char/random.c
+ * in the kernel sources */
- p += 2;
- }
+ /* Set UUID version to 4 --- truly random generation */
+ id.bytes[6] = (id.bytes[6] & 0x0F) | 0x40;
- saved_boot_id = t;
- saved_boot_id_valid = true;
+ /* Set the UUID variant to DCE */
+ id.bytes[8] = (id.bytes[8] & 0x3F) | 0x80;
- *ret = t;
- return 0;
+ return id;
}
_public_ int sd_id128_randomize(sd_id128_t *ret) {
diff --git a/src/systemd/src/systemd/sd-event.h b/src/systemd/src/systemd/sd-event.h
index 531ace1c34..cc26b7df55 100644
--- a/src/systemd/src/systemd/sd-event.h
+++ b/src/systemd/src/systemd/sd-event.h
@@ -104,6 +104,7 @@ int sd_event_get_tid(sd_event *e, pid_t *tid);
int sd_event_get_exit_code(sd_event *e, int *code);
int sd_event_set_watchdog(sd_event *e, int b);
int sd_event_get_watchdog(sd_event *e);
+int sd_event_get_iteration(sd_event *e, uint64_t *ret);
sd_event_source* sd_event_source_ref(sd_event_source *s);
sd_event_source* sd_event_source_unref(sd_event_source *s);