summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2018-06-15 15:38:52 +0200
committerThomas Haller <thaller@redhat.com>2018-06-15 15:56:04 +0200
commit13f860970af1adfa58eb5d3b408a6bdfccf4e4d7 (patch)
treeaeda946c635abab5815d548149971c9c11802da2
parent046f7599829ddc8b77e79071c05e4f4d10c72052 (diff)
parent353810ccc15b85b4e013fcc6903913c02aca1a0c (diff)
downloadNetworkManager-13f860970af1adfa58eb5d3b408a6bdfccf4e4d7.tar.gz
systemd: merge branch systemd into master
-rw-r--r--Makefile.am1
-rw-r--r--shared/nm-utils/unaligned.h4
-rw-r--r--src/systemd/sd-adapt/copy.h3
-rw-r--r--src/systemd/src/basic/alloc-util.c5
-rw-r--r--src/systemd/src/basic/alloc-util.h6
-rw-r--r--src/systemd/src/basic/async.h6
-rw-r--r--src/systemd/src/basic/escape.c11
-rw-r--r--src/systemd/src/basic/escape.h8
-rw-r--r--src/systemd/src/basic/ether-addr-util.c4
-rw-r--r--src/systemd/src/basic/ether-addr-util.h4
-rw-r--r--src/systemd/src/basic/extract-word.c5
-rw-r--r--src/systemd/src/basic/extract-word.h6
-rw-r--r--src/systemd/src/basic/fd-util.c227
-rw-r--r--src/systemd/src/basic/fd-util.h10
-rw-r--r--src/systemd/src/basic/fileio.c114
-rw-r--r--src/systemd/src/basic/fileio.h23
-rw-r--r--src/systemd/src/basic/fs-util.c44
-rw-r--r--src/systemd/src/basic/fs-util.h22
-rw-r--r--src/systemd/src/basic/hash-funcs.c5
-rw-r--r--src/systemd/src/basic/hash-funcs.h5
-rw-r--r--src/systemd/src/basic/hashmap.c5
-rw-r--r--src/systemd/src/basic/hashmap.h5
-rw-r--r--src/systemd/src/basic/hexdecoct.c5
-rw-r--r--src/systemd/src/basic/hexdecoct.h6
-rw-r--r--src/systemd/src/basic/hostname-util.c5
-rw-r--r--src/systemd/src/basic/hostname-util.h6
-rw-r--r--src/systemd/src/basic/in-addr-util.c5
-rw-r--r--src/systemd/src/basic/in-addr-util.h6
-rw-r--r--src/systemd/src/basic/io-util.c5
-rw-r--r--src/systemd/src/basic/io-util.h6
-rw-r--r--src/systemd/src/basic/list.h6
-rw-r--r--src/systemd/src/basic/log.h10
-rw-r--r--src/systemd/src/basic/macro.h8
-rw-r--r--src/systemd/src/basic/mempool.c5
-rw-r--r--src/systemd/src/basic/mempool.h6
-rw-r--r--src/systemd/src/basic/parse-util.c57
-rw-r--r--src/systemd/src/basic/parse-util.h9
-rw-r--r--src/systemd/src/basic/path-util.c212
-rw-r--r--src/systemd/src/basic/path-util.h24
-rw-r--r--src/systemd/src/basic/prioq.c5
-rw-r--r--src/systemd/src/basic/prioq.h6
-rw-r--r--src/systemd/src/basic/process-util.c59
-rw-r--r--src/systemd/src/basic/process-util.h27
-rw-r--r--src/systemd/src/basic/random-util.c9
-rw-r--r--src/systemd/src/basic/random-util.h6
-rw-r--r--src/systemd/src/basic/refcnt.h6
-rw-r--r--src/systemd/src/basic/set.h6
-rw-r--r--src/systemd/src/basic/signal-util.h6
-rw-r--r--src/systemd/src/basic/socket-util.c7
-rw-r--r--src/systemd/src/basic/socket-util.h8
-rw-r--r--src/systemd/src/basic/stat-util.c31
-rw-r--r--src/systemd/src/basic/stat-util.h7
-rw-r--r--src/systemd/src/basic/stdio-util.h6
-rw-r--r--src/systemd/src/basic/string-table.c5
-rw-r--r--src/systemd/src/basic/string-table.h22
-rw-r--r--src/systemd/src/basic/string-util.c183
-rw-r--r--src/systemd/src/basic/string-util.h33
-rw-r--r--src/systemd/src/basic/strv.c5
-rw-r--r--src/systemd/src/basic/strv.h6
-rw-r--r--src/systemd/src/basic/time-util.c41
-rw-r--r--src/systemd/src/basic/time-util.h10
-rw-r--r--src/systemd/src/basic/umask-util.h6
-rw-r--r--src/systemd/src/basic/utf8.c23
-rw-r--r--src/systemd/src/basic/utf8.h7
-rw-r--r--src/systemd/src/basic/util.c61
-rw-r--r--src/systemd/src/basic/util.h6
-rw-r--r--src/systemd/src/libsystemd-network/arp-util.c6
-rw-r--r--src/systemd/src/libsystemd-network/arp-util.h4
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-identifier.c4
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-identifier.h4
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-internal.h6
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-lease-internal.h6
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-network.c4
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-option.c4
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-packet.c6
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-protocol.h4
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-internal.h4
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-lease-internal.h6
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-network.c4
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-option.c6
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-protocol.h4
-rw-r--r--src/systemd/src/libsystemd-network/lldp-internal.h6
-rw-r--r--src/systemd/src/libsystemd-network/lldp-neighbor.c5
-rw-r--r--src/systemd/src/libsystemd-network/lldp-neighbor.h6
-rw-r--r--src/systemd/src/libsystemd-network/lldp-network.c6
-rw-r--r--src/systemd/src/libsystemd-network/lldp-network.h6
-rw-r--r--src/systemd/src/libsystemd-network/network-internal.c4
-rw-r--r--src/systemd/src/libsystemd-network/network-internal.h41
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp-client.c4
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp-lease.c8
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp6-client.c4
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp6-lease.c6
-rw-r--r--src/systemd/src/libsystemd-network/sd-ipv4acd.c6
-rw-r--r--src/systemd/src/libsystemd-network/sd-ipv4ll.c6
-rw-r--r--src/systemd/src/libsystemd-network/sd-lldp.c6
-rw-r--r--src/systemd/src/libsystemd/sd-event/sd-event.c970
-rw-r--r--src/systemd/src/libsystemd/sd-id128/id128-util.c3
-rw-r--r--src/systemd/src/libsystemd/sd-id128/id128-util.h3
-rw-r--r--src/systemd/src/libsystemd/sd-id128/sd-id128.c5
-rw-r--r--src/systemd/src/shared/dns-domain.c8
-rw-r--r--src/systemd/src/shared/dns-domain.h5
-rw-r--r--src/systemd/src/systemd/_sd-common.h3
-rw-r--r--src/systemd/src/systemd/sd-dhcp-client.h4
-rw-r--r--src/systemd/src/systemd/sd-dhcp-lease.h6
-rw-r--r--src/systemd/src/systemd/sd-dhcp6-client.h4
-rw-r--r--src/systemd/src/systemd/sd-dhcp6-lease.h6
-rw-r--r--src/systemd/src/systemd/sd-event.h10
-rw-r--r--src/systemd/src/systemd/sd-id128.h3
-rw-r--r--src/systemd/src/systemd/sd-ipv4acd.h6
-rw-r--r--src/systemd/src/systemd/sd-ipv4ll.h4
-rw-r--r--src/systemd/src/systemd/sd-lldp.h6
-rw-r--r--src/systemd/src/systemd/sd-ndisc.h4
112 files changed, 1915 insertions, 822 deletions
diff --git a/Makefile.am b/Makefile.am
index f7bc85aeff..bd8194eb70 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1303,6 +1303,7 @@ src_libsystemd_nm_la_SOURCES = \
src/systemd/sd-adapt/cgroup-util.h \
src/systemd/sd-adapt/condition.h \
src/systemd/sd-adapt/conf-parser.h \
+ src/systemd/sd-adapt/copy.h \
src/systemd/sd-adapt/def.h \
src/systemd/sd-adapt/device-nodes.h \
src/systemd/sd-adapt/dirent-util.h \
diff --git a/shared/nm-utils/unaligned.h b/shared/nm-utils/unaligned.h
index feddaa9192..965a5fe99c 100644
--- a/shared/nm-utils/unaligned.h
+++ b/shared/nm-utils/unaligned.h
@@ -2,9 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen
+ Copyright © 2014 Tom Gundersen
***/
#include <endian.h>
diff --git a/src/systemd/sd-adapt/copy.h b/src/systemd/sd-adapt/copy.h
new file mode 100644
index 0000000000..637892c2d6
--- /dev/null
+++ b/src/systemd/sd-adapt/copy.h
@@ -0,0 +1,3 @@
+#pragma once
+
+/* dummy header */
diff --git a/src/systemd/src/basic/alloc-util.c b/src/systemd/src/basic/alloc-util.c
index 79b823de42..ef40509833 100644
--- a/src/systemd/src/basic/alloc-util.c
+++ b/src/systemd/src/basic/alloc-util.c
@@ -1,9 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
#include "nm-sd-adapt.h"
diff --git a/src/systemd/src/basic/alloc-util.h b/src/systemd/src/basic/alloc-util.h
index bae6a28451..ebe42889ea 100644
--- a/src/systemd/src/basic/alloc-util.h
+++ b/src/systemd/src/basic/alloc-util.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
-
#include <alloca.h>
#include <stddef.h>
#include <stdlib.h>
diff --git a/src/systemd/src/basic/async.h b/src/systemd/src/basic/async.h
index 36f333778c..3160613184 100644
--- a/src/systemd/src/basic/async.h
+++ b/src/systemd/src/basic/async.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-***/
-
int asynchronous_job(void* (*func)(void *p), void *arg);
int asynchronous_sync(pid_t *ret_pid);
diff --git a/src/systemd/src/basic/escape.c b/src/systemd/src/basic/escape.c
index f51de788f7..5c82a545fc 100644
--- a/src/systemd/src/basic/escape.c
+++ b/src/systemd/src/basic/escape.c
@@ -1,9 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
#include "nm-sd-adapt.h"
@@ -17,8 +12,10 @@
#include "macro.h"
#include "utf8.h"
-size_t cescape_char(char c, char *buf) {
- char * buf_old = buf;
+int cescape_char(char c, char *buf) {
+ char *buf_old = buf;
+
+ /* Needs space for 4 characters in the buffer */
switch (c) {
diff --git a/src/systemd/src/basic/escape.h b/src/systemd/src/basic/escape.h
index 80b0946e2a..c612a7c02d 100644
--- a/src/systemd/src/basic/escape.h
+++ b/src/systemd/src/basic/escape.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
-
#include <inttypes.h>
#include <stddef.h>
#include <stdint.h>
@@ -47,7 +41,7 @@ typedef enum EscapeStyle {
char *cescape(const char *s);
char *cescape_length(const char *s, size_t n);
-size_t cescape_char(char c, char *buf);
+int cescape_char(char c, char *buf);
int cunescape(const char *s, UnescapeFlags flags, char **ret);
int cunescape_length(const char *s, size_t length, UnescapeFlags flags, char **ret);
diff --git a/src/systemd/src/basic/ether-addr-util.c b/src/systemd/src/basic/ether-addr-util.c
index 75de9a1902..6f946c3e92 100644
--- a/src/systemd/src/basic/ether-addr-util.c
+++ b/src/systemd/src/basic/ether-addr-util.c
@@ -1,8 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen
+ Copyright © 2014 Tom Gundersen
***/
#include "nm-sd-adapt.h"
diff --git a/src/systemd/src/basic/ether-addr-util.h b/src/systemd/src/basic/ether-addr-util.h
index f7e0de54cc..f02cefead3 100644
--- a/src/systemd/src/basic/ether-addr-util.h
+++ b/src/systemd/src/basic/ether-addr-util.h
@@ -2,9 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen
+ Copyright © 2014 Tom Gundersen
***/
#include <net/ethernet.h>
diff --git a/src/systemd/src/basic/extract-word.c b/src/systemd/src/basic/extract-word.c
index 2adb8966ea..404fe61558 100644
--- a/src/systemd/src/basic/extract-word.c
+++ b/src/systemd/src/basic/extract-word.c
@@ -1,9 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
#include "nm-sd-adapt.h"
diff --git a/src/systemd/src/basic/extract-word.h b/src/systemd/src/basic/extract-word.h
index d2113948f7..8c63b7c306 100644
--- a/src/systemd/src/basic/extract-word.h
+++ b/src/systemd/src/basic/extract-word.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
-
#include "macro.h"
typedef enum ExtractFlags {
diff --git a/src/systemd/src/basic/fd-util.c b/src/systemd/src/basic/fd-util.c
index 6a753195df..71babe2f2b 100644
--- a/src/systemd/src/basic/fd-util.c
+++ b/src/systemd/src/basic/fd-util.c
@@ -1,9 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
#include "nm-sd-adapt.h"
@@ -14,10 +9,13 @@
#include <sys/stat.h>
#include <unistd.h>
+#include "alloc-util.h"
+#include "copy.h"
#include "dirent-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
+#include "io-util.h"
#include "macro.h"
#include "memfd-util.h"
#include "missing.h"
@@ -566,6 +564,201 @@ try_dev_shm_without_o_tmpfile:
return -EOPNOTSUPP;
}
+
+/* When the data is smaller or equal to 64K, try to place the copy in a memfd/pipe */
+#define DATA_FD_MEMORY_LIMIT (64U*1024U)
+
+/* If memfd/pipe didn't work out, then let's use a file in /tmp up to a size of 1M. If it's large than that use /var/tmp instead. */
+#define DATA_FD_TMP_LIMIT (1024U*1024U)
+
+int fd_duplicate_data_fd(int fd) {
+
+ _cleanup_close_ int copy_fd = -1, tmp_fd = -1;
+ _cleanup_free_ void *remains = NULL;
+ size_t remains_size = 0;
+ const char *td;
+ struct stat st;
+ int r;
+
+ /* Creates a 'data' fd from the specified source fd, containing all the same data in a read-only fashion, but
+ * independent of it (i.e. the source fd can be closed and unmounted after this call succeeded). Tries to be
+ * somewhat smart about where to place the data. In the best case uses a memfd(). If memfd() are not supported
+ * uses a pipe instead. For larger data will use an unlinked file in /tmp, and for even larger data one in
+ * /var/tmp. */
+
+ if (fstat(fd, &st) < 0)
+ return -errno;
+
+ /* For now, let's only accept regular files, sockets, pipes and char devices */
+ if (S_ISDIR(st.st_mode))
+ return -EISDIR;
+ if (S_ISLNK(st.st_mode))
+ return -ELOOP;
+ if (!S_ISREG(st.st_mode) && !S_ISSOCK(st.st_mode) && !S_ISFIFO(st.st_mode) && !S_ISCHR(st.st_mode))
+ return -EBADFD;
+
+ /* If we have reason to believe the data is bounded in size, then let's use memfds or pipes as backing fd. Note
+ * that we use the reported regular file size only as a hint, given that there are plenty special files in
+ * /proc and /sys which report a zero file size but can be read from. */
+
+ if (!S_ISREG(st.st_mode) || st.st_size < DATA_FD_MEMORY_LIMIT) {
+
+ /* Try a memfd first */
+ copy_fd = memfd_new("data-fd");
+ if (copy_fd >= 0) {
+ off_t f;
+
+ r = copy_bytes(fd, copy_fd, DATA_FD_MEMORY_LIMIT, 0);
+ if (r < 0)
+ return r;
+
+ f = lseek(copy_fd, 0, SEEK_SET);
+ if (f != 0)
+ return -errno;
+
+ if (r == 0) {
+ /* Did it fit into the limit? If so, we are done. */
+ r = memfd_set_sealed(copy_fd);
+ if (r < 0)
+ return r;
+
+ return TAKE_FD(copy_fd);
+ }
+
+ /* Hmm, pity, this didn't fit. Let's fall back to /tmp then, see below */
+
+ } else {
+ _cleanup_(close_pairp) int pipefds[2] = { -1, -1 };
+ int isz;
+
+ /* If memfds aren't available, use a pipe. Set O_NONBLOCK so that we will get EAGAIN rather
+ * then block indefinitely when we hit the pipe size limit */
+
+ if (pipe2(pipefds, O_CLOEXEC|O_NONBLOCK) < 0)
+ return -errno;
+
+ isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0);
+ if (isz < 0)
+ return -errno;
+
+ /* Try to enlarge the pipe size if necessary */
+ if ((size_t) isz < DATA_FD_MEMORY_LIMIT) {
+
+ (void) fcntl(pipefds[1], F_SETPIPE_SZ, DATA_FD_MEMORY_LIMIT);
+
+ isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0);
+ if (isz < 0)
+ return -errno;
+ }
+
+ if ((size_t) isz >= DATA_FD_MEMORY_LIMIT) {
+
+ r = copy_bytes_full(fd, pipefds[1], DATA_FD_MEMORY_LIMIT, 0, &remains, &remains_size);
+ if (r < 0 && r != -EAGAIN)
+ return r; /* If we get EAGAIN it could be because of the source or because of
+ * the destination fd, we can't know, as sendfile() and friends won't
+ * tell us. Hence, treat this as reason to fall back, just to be
+ * sure. */
+ if (r == 0) {
+ /* Everything fit in, yay! */
+ (void) fd_nonblock(pipefds[0], false);
+
+ return TAKE_FD(pipefds[0]);
+ }
+
+ /* Things didn't fit in. But we read data into the pipe, let's remember that, so that
+ * when writing the new file we incorporate this first. */
+ copy_fd = TAKE_FD(pipefds[0]);
+ }
+ }
+ }
+
+ /* If we have reason to believe this will fit fine in /tmp, then use that as first fallback. */
+ if ((!S_ISREG(st.st_mode) || st.st_size < DATA_FD_TMP_LIMIT) &&
+ (DATA_FD_MEMORY_LIMIT + remains_size) < DATA_FD_TMP_LIMIT) {
+ off_t f;
+
+ tmp_fd = open_tmpfile_unlinkable(NULL /* NULL as directory means /tmp */, O_RDWR|O_CLOEXEC);
+ if (tmp_fd < 0)
+ return tmp_fd;
+
+ if (copy_fd >= 0) {
+ /* If we tried a memfd/pipe first and it ended up being too large, then copy this into the
+ * temporary file first. */
+
+ r = copy_bytes(copy_fd, tmp_fd, UINT64_MAX, 0);
+ if (r < 0)
+ return r;
+
+ assert(r == 0);
+ }
+
+ if (remains_size > 0) {
+ /* If there were remaining bytes (i.e. read into memory, but not written out yet) from the
+ * failed copy operation, let's flush them out next. */
+
+ r = loop_write(tmp_fd, remains, remains_size, false);
+ if (r < 0)
+ return r;
+ }
+
+ r = copy_bytes(fd, tmp_fd, DATA_FD_TMP_LIMIT - DATA_FD_MEMORY_LIMIT - remains_size, COPY_REFLINK);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ goto finish; /* Yay, it fit in */
+
+ /* It didn't fit in. Let's not forget to use what we already used */
+ f = lseek(tmp_fd, 0, SEEK_SET);
+ if (f != 0)
+ return -errno;
+
+ safe_close(copy_fd);
+ copy_fd = TAKE_FD(tmp_fd);
+
+ remains = mfree(remains);
+ remains_size = 0;
+ }
+
+ /* As last fallback use /var/tmp */
+ r = var_tmp_dir(&td);
+ if (r < 0)
+ return r;
+
+ tmp_fd = open_tmpfile_unlinkable(td, O_RDWR|O_CLOEXEC);
+ if (tmp_fd < 0)
+ return tmp_fd;
+
+ if (copy_fd >= 0) {
+ /* If we tried a memfd/pipe first, or a file in /tmp, and it ended up being too large, than copy this
+ * into the temporary file first. */
+ r = copy_bytes(copy_fd, tmp_fd, UINT64_MAX, COPY_REFLINK);
+ if (r < 0)
+ return r;
+
+ assert(r == 0);
+ }
+
+ if (remains_size > 0) {
+ /* Then, copy in any read but not yet written bytes. */
+ r = loop_write(tmp_fd, remains, remains_size, false);
+ if (r < 0)
+ return r;
+ }
+
+ /* Copy in the rest */
+ r = copy_bytes(fd, tmp_fd, UINT64_MAX, COPY_REFLINK);
+ if (r < 0)
+ return r;
+
+ assert(r == 0);
+
+finish:
+ /* Now convert the O_RDWR file descriptor into an O_RDONLY one (and as side effect seek to the beginning of the
+ * file again */
+
+ return fd_reopen(tmp_fd, O_RDONLY|O_CLOEXEC);
+}
#endif /* NM_IGNORED */
int fd_move_above_stdio(int fd) {
@@ -739,4 +932,28 @@ int fd_reopen(int fd, int flags) {
return new_fd;
}
+
+int read_nr_open(void) {
+ _cleanup_free_ char *nr_open = NULL;
+ int r;
+
+ /* Returns the kernel's current fd limit, either by reading it of /proc/sys if that works, or using the
+ * hard-coded default compiled-in value of current kernels (1M) if not. This call will never fail. */
+
+ r = read_one_line_file("/proc/sys/fs/nr_open", &nr_open);
+ if (r < 0)
+ log_debug_errno(r, "Failed to read /proc/sys/fs/nr_open, ignoring: %m");
+ else {
+ int v;
+
+ r = safe_atoi(nr_open, &v);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse /proc/sys/fs/nr_open value '%s', ignoring: %m", nr_open);
+ else
+ return v;
+ }
+
+ /* If we fail, fallback to the hard-coded kernel limit of 1024 * 1024. */
+ return 1024 * 1024;
+}
#endif /* NM_IGNORED */
diff --git a/src/systemd/src/basic/fd-util.h b/src/systemd/src/basic/fd-util.h
index 89c3f34c7b..8adc959da8 100644
--- a/src/systemd/src/basic/fd-util.h
+++ b/src/systemd/src/basic/fd-util.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
-
#include <dirent.h>
#include <stdbool.h>
#include <stdio.h>
@@ -81,6 +75,8 @@ enum {
int acquire_data_fd(const void *data, size_t size, unsigned flags);
+int fd_duplicate_data_fd(int fd);
+
/* Hint: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5 */
#define ERRNO_IS_DISCONNECT(r) \
IN_SET(r, ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, ENETUNREACH)
@@ -106,3 +102,5 @@ static inline int make_null_stdio(void) {
})
int fd_reopen(int fd, int flags);
+
+int read_nr_open(void);
diff --git a/src/systemd/src/basic/fileio.c b/src/systemd/src/basic/fileio.c
index 4f71384e39..2d3aef2c0c 100644
--- a/src/systemd/src/basic/fileio.c
+++ b/src/systemd/src/basic/fileio.c
@@ -1,9 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
#include "nm-sd-adapt.h"
@@ -209,6 +204,25 @@ fail:
return 0;
}
+int write_string_filef(
+ const char *fn,
+ WriteStringFileFlags flags,
+ const char *format, ...) {
+
+ _cleanup_free_ char *p = NULL;
+ va_list ap;
+ int r;
+
+ va_start(ap, format);
+ r = vasprintf(&p, format, ap);
+ va_end(ap);
+
+ if (r < 0)
+ return -ENOMEM;
+
+ return write_string_file(fn, p, flags);
+}
+
int read_one_line_file(const char *fn, char **line) {
_cleanup_fclose_ FILE *f = NULL;
int r;
@@ -267,29 +281,35 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
#endif /* NM_IGNORED */
int read_full_stream(FILE *f, char **contents, size_t *size) {
- size_t n, l;
_cleanup_free_ char *buf = NULL;
struct stat st;
+ size_t n, l;
+ int fd;
assert(f);
assert(contents);
- if (fstat(fileno(f), &st) < 0)
- return -errno;
-
n = LINE_MAX;
- if (S_ISREG(st.st_mode)) {
+ fd = fileno(f);
+ if (fd >= 0) { /* If the FILE* object is backed by an fd (as opposed to memory or such, see fmemopen(), let's
+ * optimize our buffering) */
- /* Safety check */
- if (st.st_size > READ_FULL_BYTES_MAX)
- return -E2BIG;
+ if (fstat(fileno(f), &st) < 0)
+ return -errno;
+
+ if (S_ISREG(st.st_mode)) {
+
+ /* Safety check */
+ if (st.st_size > READ_FULL_BYTES_MAX)
+ return -E2BIG;
- /* Start with the right file size, but be prepared for files from /proc which generally report a file
- * size of 0. Note that we increase the size to read here by one, so that the first read attempt
- * already makes us notice the EOF. */
- if (st.st_size > 0)
- n = st.st_size + 1;
+ /* Start with the right file size, but be prepared for files from /proc which generally report a file
+ * size of 0. Note that we increase the size to read here by one, so that the first read attempt
+ * already makes us notice the EOF. */
+ if (st.st_size > 0)
+ n = st.st_size + 1;
+ }
}
l = 0;
@@ -680,21 +700,41 @@ static int parse_env_file_push(
return 0;
}
-int parse_env_file(
+int parse_env_filev(
+ FILE *f,
const char *fname,
- const char *newline, ...) {
+ const char *newline,
+ va_list ap) {
- va_list ap;
int r, n_pushed = 0;
+ va_list aq;
if (!newline)
newline = NEWLINE;
+ va_copy(aq, ap);
+ r = parse_env_file_internal(f, fname, newline, parse_env_file_push, &aq, &n_pushed);
+ va_end(aq);
+ if (r < 0)
+ return r;
+
+ return n_pushed;
+}
+
+int parse_env_file(
+ FILE *f,
+ const char *fname,
+ const char *newline,
+ ...) {
+
+ va_list ap;
+ int r;
+
va_start(ap, newline);
- r = parse_env_file_internal(NULL, fname, newline, parse_env_file_push, &ap, &n_pushed);
+ r = parse_env_filev(f, fname, newline, ap);
va_end(ap);
- return r < 0 ? r : n_pushed;
+ return r;
}
#if 0 /* NM_IGNORED */
@@ -1218,7 +1258,7 @@ int tempfn_xxxxxx(const char *p, const char *extra, char **ret) {
strcpy(stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn), "XXXXXX");
- *ret = path_kill_slashes(t);
+ *ret = path_simplify(t, false);
return 0;
}
@@ -1260,7 +1300,7 @@ int tempfn_random(const char *p, const char *extra, char **ret) {
*x = 0;
- *ret = path_kill_slashes(t);
+ *ret = path_simplify(t, false);
return 0;
}
@@ -1300,7 +1340,7 @@ int tempfn_random_child(const char *p, const char *extra, char **ret) {
*x = 0;
- *ret = path_kill_slashes(t);
+ *ret = path_simplify(t, false);
return 0;
}
@@ -1528,21 +1568,29 @@ int read_nul_string(FILE *f, char **ret) {
}
int mkdtemp_malloc(const char *template, char **ret) {
- char *p;
+ _cleanup_free_ char *p = NULL;
+ int r;
- assert(template);
assert(ret);
- p = strdup(template);
+ if (template)
+ p = strdup(template);
+ else {
+ const char *tmp;
+
+ r = tmp_dir(&tmp);
+ if (r < 0)
+ return r;
+
+ p = strjoin(tmp, "/XXXXXX");
+ }
if (!p)
return -ENOMEM;
- if (!mkdtemp(p)) {
- free(p);
+ if (!mkdtemp(p))
return -errno;
- }
- *ret = p;
+ *ret = TAKE_PTR(p);
return 0;
}
diff --git a/src/systemd/src/basic/fileio.h b/src/systemd/src/basic/fileio.h
index bed7c8fb7e..77e6206e95 100644
--- a/src/systemd/src/basic/fileio.h
+++ b/src/systemd/src/basic/fileio.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
-
#include <dirent.h>
#include <stdbool.h>
#include <stddef.h>
@@ -17,12 +11,12 @@
#include "time-util.h"
typedef enum {
- WRITE_STRING_FILE_CREATE = 1<<0,
- WRITE_STRING_FILE_ATOMIC = 1<<1,
- WRITE_STRING_FILE_AVOID_NEWLINE = 1<<2,
- WRITE_STRING_FILE_VERIFY_ON_FAILURE = 1<<3,
- WRITE_STRING_FILE_SYNC = 1<<4,
- WRITE_STRING_FILE_DISABLE_BUFFER = 1<<5,
+ WRITE_STRING_FILE_CREATE = 1 << 0,
+ WRITE_STRING_FILE_ATOMIC = 1 << 1,
+ WRITE_STRING_FILE_AVOID_NEWLINE = 1 << 2,
+ WRITE_STRING_FILE_VERIFY_ON_FAILURE = 1 << 3,
+ WRITE_STRING_FILE_SYNC = 1 << 4,
+ WRITE_STRING_FILE_DISABLE_BUFFER = 1 << 5,
/* And before you wonder, why write_string_file_atomic_label_ts() is a separate function instead of just one
more flag here: it's about linking: we don't want to pull -lselinux into all users of write_string_file()
@@ -39,13 +33,16 @@ static inline int write_string_file(const char *fn, const char *line, WriteStrin
return write_string_file_ts(fn, line, flags, NULL);
}
+int write_string_filef(const char *fn, WriteStringFileFlags flags, const char *format, ...) _printf_(3, 4);
+
int read_one_line_file(const char *fn, char **line);
int read_full_file(const char *fn, char **contents, size_t *size);
int read_full_stream(FILE *f, char **contents, size_t *size);
int verify_file(const char *fn, const char *blob, bool accept_extra_nl);
-int parse_env_file(const char *fname, const char *separator, ...) _sentinel_;
+int parse_env_filev(FILE *f, const char *fname, const char *separator, va_list ap);
+int parse_env_file(FILE *f, const char *fname, const char *separator, ...) _sentinel_;
int load_env_file(FILE *f, const char *fname, const char *separator, char ***l);
int load_env_file_pairs(FILE *f, const char *fname, const char *separator, char ***l);
diff --git a/src/systemd/src/basic/fs-util.c b/src/systemd/src/basic/fs-util.c
index 049b238e8d..e3ae991605 100644
--- a/src/systemd/src/basic/fs-util.c
+++ b/src/systemd/src/basic/fs-util.c
@@ -1,9 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
#include "nm-sd-adapt.h"
@@ -234,6 +229,22 @@ int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
return 0;
}
+
+int fchmod_and_chown(int fd, mode_t mode, uid_t uid, gid_t gid) {
+ /* Under the assumption that we are running privileged we
+ * first change the access mode and only then hand out
+ * ownership to avoid a window where access is too open. */
+
+ if (mode != MODE_INVALID)
+ if (fchmod(fd, mode) < 0)
+ return -errno;
+
+ if (uid != UID_INVALID || gid != GID_INVALID)
+ if (fchown(fd, uid, gid) < 0)
+ return -errno;
+
+ return 0;
+}
#endif /* NM_IGNORED */
int fchmod_umask(int fd, mode_t m) {
@@ -249,7 +260,7 @@ int fchmod_umask(int fd, mode_t m) {
#if 0 /* NM_IGNORED */
int fchmod_opath(int fd, mode_t m) {
- char procfs_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+ char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
/* This function operates also on fd that might have been opened with
* O_PATH. Indeed fchmodat() doesn't have the AT_EMPTY_PATH flag like
@@ -571,6 +582,7 @@ int unlink_or_warn(const char *filename) {
return 0;
}
+#endif /* NM_IGNORED */
int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
char path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
@@ -586,6 +598,7 @@ int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
return r;
}
+#if 0 /* NM_IGNORED */
static bool safe_transition(const struct stat *a, const struct stat *b) {
/* Returns true if the transition from a to b is safe, i.e. that we never transition from unprivileged to
* privileged files or directories. Why bother? So that unprivileged code can't symlink to privileged files
@@ -609,10 +622,10 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
assert(path);
/* Either the file may be missing, or we return an fd to the final object, but both make no sense */
- if ((flags & (CHASE_NONEXISTENT|CHASE_OPEN)) == (CHASE_NONEXISTENT|CHASE_OPEN))
+ if (FLAGS_SET(flags, CHASE_NONEXISTENT | CHASE_OPEN))
return -EINVAL;
- if ((flags & (CHASE_STEP|CHASE_OPEN)) == (CHASE_STEP|CHASE_OPEN))
+ if (FLAGS_SET(flags, CHASE_STEP | CHASE_OPEN))
return -EINVAL;
if (isempty(path))
@@ -1073,6 +1086,15 @@ int access_fd(int fd, int mode) {
return r;
}
+void unlink_tempfilep(char (*p)[]) {
+ /* If the file is created with mkstemp(), it will (almost always)
+ * change the suffix. Treat this as a sign that the file was
+ * successfully created. We ignore both the rare case where the
+ * original suffix is used and unlink failures. */
+ if (!endswith(*p, ".XXXXXX"))
+ (void) unlink_noerrno(*p);
+}
+
int unlinkat_deallocate(int fd, const char *name, int flags) {
_cleanup_close_ int truncate_fd = -1;
struct stat st;
@@ -1153,9 +1175,9 @@ int fsync_directory_of_file(int fd) {
r = fd_get_path(fd, &path);
if (r < 0) {
- log_debug("Failed to query /proc/self/fd/%d%s: %m",
- fd,
- r == -EOPNOTSUPP ? ", ignoring" : "");
+ log_debug_errno(r, "Failed to query /proc/self/fd/%d%s: %m",
+ fd,
+ r == -EOPNOTSUPP ? ", ignoring" : "");
if (r == -EOPNOTSUPP)
/* If /proc is not available, we're most likely running in some
diff --git a/src/systemd/src/basic/fs-util.h b/src/systemd/src/basic/fs-util.h
index 6157fe81bf..28566773c6 100644
--- a/src/systemd/src/basic/fs-util.h
+++ b/src/systemd/src/basic/fs-util.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
-
#include <dirent.h>
#include <fcntl.h>
#include <limits.h>
@@ -31,6 +25,7 @@ int readlink_value(const char *p, char **ret);
int readlink_and_make_absolute(const char *p, char **r);
int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
+int fchmod_and_chown(int fd, mode_t mode, uid_t uid, gid_t gid);
int fchmod_umask(int fd, mode_t mode);
int fchmod_opath(int fd, mode_t m);
@@ -70,13 +65,13 @@ union inotify_event_buffer {
int inotify_add_watch_fd(int fd, int what, uint32_t mask);
enum {
- CHASE_PREFIX_ROOT = 1U << 0, /* If set, the specified path will be prefixed by the specified root before beginning the iteration */
- CHASE_NONEXISTENT = 1U << 1, /* If set, it's OK if the path doesn't actually exist. */
- CHASE_NO_AUTOFS = 1U << 2, /* If set, return -EREMOTE if autofs mount point found */
- CHASE_SAFE = 1U << 3, /* If set, return EPERM if we ever traverse from unprivileged to privileged files or directories */
- CHASE_OPEN = 1U << 4, /* If set, return an O_PATH object to the final component */
- CHASE_TRAIL_SLASH = 1U << 5, /* If set, any trailing slash will be preserved */
- CHASE_STEP = 1U << 6, /* If set, just execute a single step of the normalization */
+ CHASE_PREFIX_ROOT = 1 << 0, /* If set, the specified path will be prefixed by the specified root before beginning the iteration */
+ CHASE_NONEXISTENT = 1 << 1, /* If set, it's OK if the path doesn't actually exist. */
+ CHASE_NO_AUTOFS = 1 << 2, /* If set, return -EREMOTE if autofs mount point found */
+ CHASE_SAFE = 1 << 3, /* If set, return EPERM if we ever traverse from unprivileged to privileged files or directories */
+ CHASE_OPEN = 1 << 4, /* If set, return an O_PATH object to the final component */
+ CHASE_TRAIL_SLASH = 1 << 5, /* If set, any trailing slash will be preserved */
+ CHASE_STEP = 1 << 6, /* If set, just execute a single step of the normalization */
};
/* How many iterations to execute before returning -ELOOP */
@@ -104,6 +99,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(char*, unlink_and_free);
int access_fd(int fd, int mode);
+void unlink_tempfilep(char (*p)[]);
int unlinkat_deallocate(int fd, const char *name, int flags);
int fsync_directory_of_file(int fd);
diff --git a/src/systemd/src/basic/hash-funcs.c b/src/systemd/src/basic/hash-funcs.c
index cb763f56fb..7ed35cb165 100644
--- a/src/systemd/src/basic/hash-funcs.c
+++ b/src/systemd/src/basic/hash-funcs.c
@@ -1,9 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2014 Michal Schmidt
+ Copyright © 2014 Michal Schmidt
***/
#include "nm-sd-adapt.h"
diff --git a/src/systemd/src/basic/hash-funcs.h b/src/systemd/src/basic/hash-funcs.h
index 0c963af8ef..3715c56e07 100644
--- a/src/systemd/src/basic/hash-funcs.h
+++ b/src/systemd/src/basic/hash-funcs.h
@@ -2,10 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2014 Michal Schmidt
+ Copyright © 2014 Michal Schmidt
***/
#include "macro.h"
diff --git a/src/systemd/src/basic/hashmap.c b/src/systemd/src/basic/hashmap.c
index b8a8e37b5c..c91f8bd23a 100644
--- a/src/systemd/src/basic/hashmap.c
+++ b/src/systemd/src/basic/hashmap.c
@@ -1,9 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2014 Michal Schmidt
+ Copyright © 2014 Michal Schmidt
***/
#include "nm-sd-adapt.h"
diff --git a/src/systemd/src/basic/hashmap.h b/src/systemd/src/basic/hashmap.h
index 701eecbdb0..d1d1b9c8a4 100644
--- a/src/systemd/src/basic/hashmap.h
+++ b/src/systemd/src/basic/hashmap.h
@@ -2,10 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2014 Michal Schmidt
+ Copyright © 2014 Michal Schmidt
***/
#include <limits.h>
diff --git a/src/systemd/src/basic/hexdecoct.c b/src/systemd/src/basic/hexdecoct.c
index 1fe410f56a..09f2a9e711 100644
--- a/src/systemd/src/basic/hexdecoct.c
+++ b/src/systemd/src/basic/hexdecoct.c
@@ -1,9 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
#include "nm-sd-adapt.h"
diff --git a/src/systemd/src/basic/hexdecoct.h b/src/systemd/src/basic/hexdecoct.h
index c2f11013e5..9477d16e37 100644
--- a/src/systemd/src/basic/hexdecoct.h
+++ b/src/systemd/src/basic/hexdecoct.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
-
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
diff --git a/src/systemd/src/basic/hostname-util.c b/src/systemd/src/basic/hostname-util.c
index 0feeaa5d31..85708394b7 100644
--- a/src/systemd/src/basic/hostname-util.c
+++ b/src/systemd/src/basic/hostname-util.c
@@ -1,9 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-***/
#include "nm-sd-adapt.h"
diff --git a/src/systemd/src/basic/hostname-util.h b/src/systemd/src/basic/hostname-util.h
index 8e29e9e1e5..749481723d 100644
--- a/src/systemd/src/basic/hostname-util.h
+++ b/src/systemd/src/basic/hostname-util.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010-2015 Lennart Poettering
-***/
-
#include <stdbool.h>
#include <stdio.h>
diff --git a/src/systemd/src/basic/in-addr-util.c b/src/systemd/src/basic/in-addr-util.c
index 65748615b0..d945567aee 100644
--- a/src/systemd/src/basic/in-addr-util.c
+++ b/src/systemd/src/basic/in-addr-util.c
@@ -1,9 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-***/
#include "nm-sd-adapt.h"
diff --git a/src/systemd/src/basic/in-addr-util.h b/src/systemd/src/basic/in-addr-util.h
index acd567c994..956c00a850 100644
--- a/src/systemd/src/basic/in-addr-util.h
+++ b/src/systemd/src/basic/in-addr-util.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-***/
-
#include <netinet/in.h>
#include <stddef.h>
#include <sys/socket.h>
diff --git a/src/systemd/src/basic/io-util.c b/src/systemd/src/basic/io-util.c
index 1bc5c34599..6f46c944ea 100644
--- a/src/systemd/src/basic/io-util.c
+++ b/src/systemd/src/basic/io-util.c
@@ -1,9 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
#include "nm-sd-adapt.h"
diff --git a/src/systemd/src/basic/io-util.h b/src/systemd/src/basic/io-util.h
index e4717b6f30..ed189b5820 100644
--- a/src/systemd/src/basic/io-util.h
+++ b/src/systemd/src/basic/io-util.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
-
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
diff --git a/src/systemd/src/basic/list.h b/src/systemd/src/basic/list.h
index 3ec7e73fc5..643e0bea88 100644
--- a/src/systemd/src/basic/list.h
+++ b/src/systemd/src/basic/list.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
-
/* The head of the linked list. Use this in the structure that shall
* contain the head of the linked list */
#define LIST_HEAD(t,name) \
diff --git a/src/systemd/src/basic/log.h b/src/systemd/src/basic/log.h
index e7d7c8b14d..28edd57255 100644
--- a/src/systemd/src/basic/log.h
+++ b/src/systemd/src/basic/log.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
-
#include <stdarg.h>
#include <stdbool.h>
#include <stdlib.h>
@@ -251,7 +245,7 @@ int log_emergency_level(void);
/* Structured logging */
#define log_struct_errno(level, error, ...) \
log_struct_internal(LOG_REALM_PLUS_LEVEL(LOG_REALM, level), \
- error, __FILE__, __LINE__, __func__, __VA_ARGS__)
+ error, __FILE__, __LINE__, __func__, __VA_ARGS__, NULL)
#define log_struct(level, ...) log_struct_errno(level, 0, __VA_ARGS__)
#define log_struct_iovec_errno(level, error, iovec, n_iovec) \
@@ -290,6 +284,8 @@ void log_set_open_when_needed(bool b);
* stderr, the console or kmsg */
void log_set_prohibit_ipc(bool b);
+int log_dup_console(void);
+
int log_syntax_internal(
const char *unit,
int level,
diff --git a/src/systemd/src/basic/macro.h b/src/systemd/src/basic/macro.h
index c89fb84ed5..cdb54f82ac 100644
--- a/src/systemd/src/basic/macro.h
+++ b/src/systemd/src/basic/macro.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
-
#include <inttypes.h>
#include <stdbool.h>
#include <sys/param.h>
@@ -366,6 +360,8 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
#define SET_FLAG(v, flag, b) \
(v) = (b) ? ((v) | (flag)) : ((v) & ~(flag))
+#define FLAGS_SET(v, flags) \
+ (((v) & (flags)) == (flags))
#define CASE_F(X) case X:
#define CASE_F_1(CASE, X) CASE_F(X)
diff --git a/src/systemd/src/basic/mempool.c b/src/systemd/src/basic/mempool.c
index 0709676696..a0154263f2 100644
--- a/src/systemd/src/basic/mempool.c
+++ b/src/systemd/src/basic/mempool.c
@@ -1,9 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2010-2014 Lennart Poettering
- Copyright 2014 Michal Schmidt
+ Copyright © 2014 Michal Schmidt
***/
#include "nm-sd-adapt.h"
diff --git a/src/systemd/src/basic/mempool.h b/src/systemd/src/basic/mempool.h
index 68249cd881..291415deb0 100644
--- a/src/systemd/src/basic/mempool.h
+++ b/src/systemd/src/basic/mempool.h
@@ -2,10 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2011-2014 Lennart Poettering
- Copyright 2014 Michal Schmidt
+ Copyright © 2014 Michal Schmidt
***/
#include <stddef.h>
@@ -29,7 +26,6 @@ static struct mempool pool_name = { \
.at_least = alloc_at_least, \
}
-
#if VALGRIND
void mempool_drop(struct mempool *mp);
#endif
diff --git a/src/systemd/src/basic/parse-util.c b/src/systemd/src/basic/parse-util.c
index ae43a0411b..7d6bcb5a45 100644
--- a/src/systemd/src/basic/parse-util.c
+++ b/src/systemd/src/basic/parse-util.c
@@ -1,9 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
#include "nm-sd-adapt.h"
@@ -637,6 +632,58 @@ int parse_percent(const char *p) {
return v;
}
+int parse_permille_unbounded(const char *p) {
+ const char *pc, *pm, *dot, *n;
+ int r, q, v;
+
+ pm = endswith(p, "‰");
+ if (pm) {
+ n = strndupa(p, pm - p);
+ r = safe_atoi(n, &v);
+ if (r < 0)
+ return r;
+ } else {
+ pc = endswith(p, "%");
+ if (!pc)
+ return -EINVAL;
+
+ dot = memchr(p, '.', pc - p);
+ if (dot) {
+ if (dot + 2 != pc)
+ return -EINVAL;
+ if (dot[1] < '0' || dot[1] > '9')
+ return -EINVAL;
+ q = dot[1] - '0';
+ n = strndupa(p, dot - p);
+ } else {
+ q = 0;
+ n = strndupa(p, pc - p);
+ }
+ r = safe_atoi(n, &v);
+ if (r < 0)
+ return r;
+ if (v > (INT_MAX - q) / 10)
+ return -ERANGE;
+
+ v = v * 10 + q;
+ }
+
+ if (v < 0)
+ return -ERANGE;
+
+ return v;
+}
+
+int parse_permille(const char *p) {
+ int v;
+
+ v = parse_permille_unbounded(p);
+ if (v > 1000)
+ return -ERANGE;
+
+ return v;
+}
+
int parse_nice(const char *p, int *ret) {
int n, r;
diff --git a/src/systemd/src/basic/parse-util.h b/src/systemd/src/basic/parse-util.h
index 2b75b938c7..f3267f4cfe 100644
--- a/src/systemd/src/basic/parse-util.h
+++ b/src/systemd/src/basic/parse-util.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
-
#include <inttypes.h>
#include <limits.h>
#include <stddef.h>
@@ -115,6 +109,9 @@ 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_permille_unbounded(const char *p);
+int parse_permille(const char *p);
+
int parse_nice(const char *p, int *ret);
int parse_ip_port(const char *s, uint16_t *ret);
diff --git a/src/systemd/src/basic/path-util.c b/src/systemd/src/basic/path-util.c
index 567fc61cea..69bdb894cf 100644
--- a/src/systemd/src/basic/path-util.c
+++ b/src/systemd/src/basic/path-util.c
@@ -1,9 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010-2012 Lennart Poettering
-***/
#include "nm-sd-adapt.h"
@@ -34,12 +29,13 @@
#include "string-util.h"
#include "strv.h"
#include "time-util.h"
+#include "utf8.h"
-#if 0 /* NM_IGNORED */
bool path_is_absolute(const char *p) {
return p[0] == '/';
}
+#if 0 /* NM_IGNORED */
bool is_path(const char *p) {
return !!strchr(p, '/');
}
@@ -130,8 +126,8 @@ int path_make_absolute_cwd(const char *p, char **ret) {
}
int path_make_relative(const char *from_dir, const char *to_path, char **_r) {
- char *r, *p;
- unsigned n_parents;
+ char *f, *t, *r, *p;
+ unsigned n_parents = 0;
assert(from_dir);
assert(to_path);
@@ -139,85 +135,81 @@ int path_make_relative(const char *from_dir, const char *to_path, char **_r) {
/* Strips the common part, and adds ".." elements as necessary. */
- if (!path_is_absolute(from_dir))
+ if (!path_is_absolute(from_dir) || !path_is_absolute(to_path))
return -EINVAL;
- if (!path_is_absolute(to_path))
- return -EINVAL;
+ f = strdupa(from_dir);
+ t = strdupa(to_path);
+
+ path_simplify(f, true);
+ path_simplify(t, true);
/* Skip the common part. */
for (;;) {
size_t a, b;
- from_dir += strspn(from_dir, "/");
- to_path += strspn(to_path, "/");
+ f += *f == '/';
+ t += *t == '/';
- if (!*from_dir) {
- if (!*to_path)
+ if (!*f) {
+ if (!*t)
/* from_dir equals to_path. */
r = strdup(".");
else
/* from_dir is a parent directory of to_path. */
- r = strdup(to_path);
+ r = strdup(t);
if (!r)
return -ENOMEM;
- path_kill_slashes(r);
-
*_r = r;
return 0;
}
- if (!*to_path)
+ if (!*t)
break;
- a = strcspn(from_dir, "/");
- b = strcspn(to_path, "/");
+ a = strcspn(f, "/");
+ b = strcspn(t, "/");
- if (a != b)
+ if (a != b || memcmp(f, t, a) != 0)
break;
- if (memcmp(from_dir, to_path, a) != 0)
- break;
-
- from_dir += a;
- to_path += b;
+ f += a;
+ t += b;
}
/* If we're here, then "from_dir" has one or more elements that need to
* be replaced with "..". */
/* Count the number of necessary ".." elements. */
- for (n_parents = 0;;) {
+ for (; *f;) {
size_t w;
- from_dir += strspn(from_dir, "/");
-
- if (!*from_dir)
- break;
-
- w = strcspn(from_dir, "/");
+ w = strcspn(f, "/");
/* If this includes ".." we can't do a simple series of "..", refuse */
- if (w == 2 && from_dir[0] == '.' && from_dir[1] == '.')
+ if (w == 2 && f[0] == '.' && f[1] == '.')
return -EINVAL;
- /* Count number of elements, except if they are "." */
- if (w != 1 || from_dir[0] != '.')
- n_parents++;
+ /* Count number of elements */
+ n_parents++;
- from_dir += w;
+ f += w;
+ f += *f == '/';
}
- r = new(char, n_parents * 3 + strlen(to_path) + 1);
+ r = new(char, n_parents * 3 + strlen(t) + 1);
if (!r)
return -ENOMEM;
for (p = r; n_parents > 0; n_parents--)
p = mempcpy(p, "../", 3);
- strcpy(p, to_path);
- path_kill_slashes(r);
+ if (*t)
+ strcpy(p, t);
+ else
+ /* Remove trailing slash */
+ *(--p) = 0;
*_r = r;
return 0;
@@ -238,7 +230,7 @@ int path_strv_make_absolute_cwd(char **l) {
if (r < 0)
return r;
- path_kill_slashes(t);
+ path_simplify(t, false);
free_and_replace(*s, t);
}
@@ -339,17 +331,30 @@ char **path_strv_resolve_uniq(char **l, const char *root) {
}
#endif /* NM_IGNORED */
-char *path_kill_slashes(char *path) {
+char *path_simplify(char *path, bool kill_dots) {
char *f, *t;
- bool slash = false;
+ bool slash = false, ignore_slash = false, absolute;
+
+ assert(path);
- /* Removes redundant inner and trailing slashes. Modifies the
- * passed string in-place.
+ /* 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
+ * ///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)
*/
- for (f = path, t = path; *f; f++) {
+ absolute = path_is_absolute(path);
+
+ f = path;
+ if (kill_dots && *f == '.' && IN_SET(f[1], 0, '/')) {
+ ignore_slash = true;
+ f++;
+ }
+
+ for (t = path; *f; f++) {
if (*f == '/') {
slash = true;
@@ -357,17 +362,21 @@ char *path_kill_slashes(char *path) {
}
if (slash) {
+ if (kill_dots && *f == '.' && IN_SET(f[1], 0, '/'))
+ continue;
+
slash = false;
- *(t++) = '/';
+ if (ignore_slash)
+ ignore_slash = false;
+ else
+ *(t++) = '/';
}
*(t++) = *f;
}
- /* Special rule, if we are talking of the root directory, a
- trailing slash is good */
-
- if (t == path && slash)
+ /* Special rule, if we are talking of the root directory, a trailing slash is good */
+ if (absolute && t == path)
*(t++) = '/';
*t = 0;
@@ -535,7 +544,7 @@ int find_binary(const char *name, char **ret) {
/* Found it! */
if (ret) {
- *ret = path_kill_slashes(j);
+ *ret = path_simplify(j, false);
j = NULL;
}
@@ -689,12 +698,11 @@ int parse_path_argument_and_warn(const char *path, bool suppress_root, char **ar
if (r < 0)
return log_error_errno(r, "Failed to parse path \"%s\" and make it absolute: %m", path);
- path_kill_slashes(p);
+ path_simplify(p, false);
if (suppress_root && empty_or_root(p))
p = mfree(p);
- free(*arg);
- *arg = p;
+ free_and_replace(*arg, p);
return 0;
}
@@ -778,7 +786,6 @@ bool filename_is_valid(const char *p) {
return true;
}
-#if 0 /* NM_IGNORED */
bool path_is_normalized(const char *p) {
if (isempty(p))
@@ -802,6 +809,7 @@ bool path_is_normalized(const char *p) {
return true;
}
+#if 0 /* NM_IGNORED */
char *file_in_same_dir(const char *path, const char *filename) {
char *e, *ret;
size_t k;
@@ -880,17 +888,36 @@ bool hidden_or_backup_file(const char *filename) {
bool is_device_path(const char *path) {
- /* Returns true on paths that refer to a device, either in
- * sysfs or in /dev */
+ /* Returns true on paths that likely refer to a device, either by path in sysfs or to something in /dev */
+
+ return PATH_STARTSWITH_SET(path, "/dev/", "/sys/");
+}
+
+bool valid_device_node_path(const char *path) {
+
+ /* Some superficial checks whether the specified path is a valid device node path, all without looking at the
+ * actual device node. */
+
+ if (!PATH_STARTSWITH_SET(path, "/dev/", "/run/systemd/inaccessible/"))
+ return false;
+
+ if (endswith(path, "/")) /* can't be a device node if it ends in a slash */
+ return false;
- return path_startswith(path, "/dev/") ||
- path_startswith(path, "/sys/");
+ return path_is_normalized(path);
}
-bool is_deviceallow_pattern(const char *path) {
- return path_startswith(path, "/dev/") ||
- startswith(path, "block-") ||
- startswith(path, "char-");
+bool valid_device_allow_pattern(const char *path) {
+ assert(path);
+
+ /* Like valid_device_node_path(), but also allows full-subsystem expressions, like DeviceAllow= and DeviceDeny=
+ * accept it */
+
+ if (startswith(path, "block-") ||
+ startswith(path, "char-"))
+ return true;
+
+ return valid_device_node_path(path);
}
int systemd_installation_has_version(const char *root, unsigned minimal_version) {
@@ -926,7 +953,7 @@ int systemd_installation_has_version(const char *root, unsigned minimal_version)
if (r < 0)
return r;
- assert_se((c = endswith(path, "*.so")));
+ assert_se(c = endswith(path, "*.so"));
*c = '\0'; /* truncate the glob part */
STRV_FOREACH(name, names) {
@@ -975,6 +1002,7 @@ bool dot_or_dot_dot(const char *path) {
return path[2] == 0;
}
+#if 0 /* NM_IGNORED */
bool empty_or_root(const char *root) {
/* For operations relative to some root directory, returns true if the specified root directory is redundant,
@@ -985,3 +1013,51 @@ bool empty_or_root(const char *root) {
return root[strspn(root, "/")] == 0;
}
+
+int path_simplify_and_warn(
+ char *path,
+ unsigned flag,
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *lvalue) {
+
+ bool absolute, fatal = flag & PATH_CHECK_FATAL;
+
+ assert(!FLAGS_SET(flag, PATH_CHECK_ABSOLUTE | PATH_CHECK_RELATIVE));
+
+ if (!utf8_is_valid(path)) {
+ log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, path);
+ return -EINVAL;
+ }
+
+ if (flag & (PATH_CHECK_ABSOLUTE | PATH_CHECK_RELATIVE)) {
+ absolute = path_is_absolute(path);
+
+ if (!absolute && (flag & PATH_CHECK_ABSOLUTE)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "%s= path is not absolute%s: %s",
+ lvalue, fatal ? "" : ", ignoring", path);
+ return -EINVAL;
+ }
+
+ if (absolute && (flag & PATH_CHECK_RELATIVE)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "%s= path is absolute%s: %s",
+ lvalue, fatal ? "" : ", ignoring", path);
+ return -EINVAL;
+ }
+ }
+
+ path_simplify(path, true);
+
+ if (!path_is_normalized(path)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "%s= path is not normalized%s: %s",
+ lvalue, fatal ? "" : ", ignoring", path);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+#endif /* NM_IGNORED */
diff --git a/src/systemd/src/basic/path-util.h b/src/systemd/src/basic/path-util.h
index 79db819e4d..519060cf53 100644
--- a/src/systemd/src/basic/path-util.h
+++ b/src/systemd/src/basic/path-util.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010-2012 Lennart Poettering
-***/
-
#include <alloca.h>
#include <stdbool.h>
#include <stddef.h>
@@ -52,12 +46,12 @@ char* path_make_absolute(const char *p, const char *prefix);
int safe_getcwd(char **ret);
int path_make_absolute_cwd(const char *p, char **ret);
int path_make_relative(const char *from_dir, const char *to_path, char **_r);
-char* path_kill_slashes(char *path);
char* path_startswith(const char *path, const char *prefix) _pure_;
int path_compare(const char *a, const char *b) _pure_;
bool path_equal(const char *a, const char *b) _pure_;
bool path_equal_or_files_same(const char *a, const char *b, int flags);
char* path_join(const char *root, const char *path, const char *rest);
+char* path_simplify(char *path, bool kill_dots);
static inline bool path_equal_ptr(const char *a, const char *b) {
return !!a == !!b && (!a || path_equal(a, b));
@@ -103,11 +97,11 @@ int mkfs_exists(const char *fstype);
* the tree, to root. Also returns "" (and not "/"!) for the root
* directory. Excludes the specified directory itself */
#define PATH_FOREACH_PREFIX(prefix, path) \
- for (char *_slash = ({ path_kill_slashes(strcpy(prefix, path)); streq(prefix, "/") ? NULL : strrchr(prefix, '/'); }); _slash && ((*_slash = 0), true); _slash = strrchr((prefix), '/'))
+ for (char *_slash = ({ path_simplify(strcpy(prefix, path), false); streq(prefix, "/") ? NULL : strrchr(prefix, '/'); }); _slash && ((*_slash = 0), true); _slash = strrchr((prefix), '/'))
/* Same as PATH_FOREACH_PREFIX but also includes the specified path itself */
#define PATH_FOREACH_PREFIX_MORE(prefix, path) \
- for (char *_slash = ({ path_kill_slashes(strcpy(prefix, path)); if (streq(prefix, "/")) prefix[0] = 0; strrchr(prefix, 0); }); _slash && ((*_slash = 0), true); _slash = strrchr((prefix), '/'))
+ for (char *_slash = ({ path_simplify(strcpy(prefix, path), false); if (streq(prefix, "/")) prefix[0] = 0; strrchr(prefix, 0); }); _slash && ((*_slash = 0), true); _slash = strrchr((prefix), '/'))
char *prefix_root(const char *root, const char *path);
@@ -149,7 +143,9 @@ char *file_in_same_dir(const char *path, const char *filename);
bool hidden_or_backup_file(const char *filename) _pure_;
bool is_device_path(const char *path);
-bool is_deviceallow_pattern(const char *path);
+
+bool valid_device_node_path(const char *path);
+bool valid_device_allow_pattern(const char *path);
int systemd_installation_has_version(const char *root, unsigned minimal_version);
@@ -169,3 +165,11 @@ bool empty_or_root(const char *root);
static inline const char *empty_to_root(const char *path) {
return isempty(path) ? "/" : path;
}
+
+enum {
+ PATH_CHECK_FATAL = 1 << 0, /* If not set, then error message is appended with 'ignoring'. */
+ PATH_CHECK_ABSOLUTE = 1 << 1,
+ PATH_CHECK_RELATIVE = 1 << 2,
+};
+
+int path_simplify_and_warn(char *path, unsigned flag, const char *unit, const char *filename, unsigned line, const char *lvalue);
diff --git a/src/systemd/src/basic/prioq.c b/src/systemd/src/basic/prioq.c
index 805a617458..79900df353 100644
--- a/src/systemd/src/basic/prioq.c
+++ b/src/systemd/src/basic/prioq.c
@@ -1,9 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-***/
/*
* Priority Queue
diff --git a/src/systemd/src/basic/prioq.h b/src/systemd/src/basic/prioq.h
index e348c64649..e036175260 100644
--- a/src/systemd/src/basic/prioq.h
+++ b/src/systemd/src/basic/prioq.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-***/
-
#include <stdbool.h>
#include "hashmap.h"
diff --git a/src/systemd/src/basic/process-util.c b/src/systemd/src/basic/process-util.c
index 4af99957d2..10aa0e56d5 100644
--- a/src/systemd/src/basic/process-util.c
+++ b/src/systemd/src/basic/process-util.c
@@ -1,9 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
#include "nm-sd-adapt.h"
@@ -19,6 +14,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
+#include <sys/mount.h>
#include <sys/personality.h>
#include <sys/prctl.h>
#include <sys/types.h>
@@ -80,20 +76,31 @@ int get_process_state(pid_t pid) {
return (unsigned char) state;
}
-int get_process_comm(pid_t pid, char **name) {
+int get_process_comm(pid_t pid, char **ret) {
+ _cleanup_free_ char *escaped = NULL, *comm = NULL;
const char *p;
int r;
- assert(name);
+ assert(ret);
assert(pid >= 0);
+ escaped = new(char, TASK_COMM_LEN);
+ if (!escaped)
+ return -ENOMEM;
+
p = procfs_file_alloca(pid, "comm");
- r = read_one_line_file(p, name);
+ r = read_one_line_file(p, &comm);
if (r == -ENOENT)
return -ESRCH;
+ if (r < 0)
+ return r;
- return r;
+ /* Escape unprintable characters, just in case, but don't grow the string beyond the underlying size */
+ cellescape(escaped, TASK_COMM_LEN, comm);
+
+ *ret = TAKE_PTR(escaped);
+ return 0;
}
int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) {
@@ -251,15 +258,10 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
memcpy(ans, "[...]", max_length-1);
ans[max_length-1] = 0;
} else {
- char *e;
-
t[max_length - 6] = 0;
/* Chop off final spaces */
- e = strchr(t, 0);
- while (e > t && isspace(e[-1]))
- e--;
- *e = 0;
+ delete_trailing_chars(t, WHITESPACE);
ans = strjoin("[", t, "...]");
}
@@ -300,7 +302,7 @@ int rename_process(const char name[]) {
* can use PR_SET_NAME, which sets the thread name for the calling thread. */
if (prctl(PR_SET_NAME, name) < 0)
log_debug_errno(errno, "PR_SET_NAME failed: %m");
- if (l > 15) /* Linux process names can be 15 chars at max */
+ if (l >= TASK_COMM_LEN) /* Linux process names can be 15 chars at max */
truncated = true;
/* Second step, change glibc's ID of the process name. */
@@ -744,14 +746,17 @@ int wait_for_terminate_and_check(const char *name, pid_t pid, WaitFlags flags) {
/*
* Return values:
- * < 0 : wait_for_terminate_with_timeout() failed to get the state of the
- * process, the process timed out, the process was terminated by a
- * signal, or failed for an unknown reason.
+ *
+ * < 0 : wait_for_terminate_with_timeout() failed to get the state of the process, the process timed out, the process
+ * was terminated by a signal, or failed for an unknown reason.
+ *
* >=0 : The process terminated normally with no failures.
*
- * Success is indicated by a return value of zero, a timeout is indicated
- * by ETIMEDOUT, and all other child failure states are indicated by error
- * is indicated by a non-zero value.
+ * Success is indicated by a return value of zero, a timeout is indicated by ETIMEDOUT, and all other child failure
+ * states are indicated by error is indicated by a non-zero value.
+ *
+ * This call assumes SIGCHLD has been blocked already, in particular before the child to wait for has been forked off
+ * to remain entirely race-free.
*/
int wait_for_terminate_with_timeout(pid_t pid, usec_t timeout) {
sigset_t mask;
@@ -1353,6 +1358,16 @@ int safe_fork_full(
}
}
+ if (FLAGS_SET(flags, FORK_NEW_MOUNTNS | FORK_MOUNTNS_SLAVE)) {
+
+ /* Optionally, make sure we never propagate mounts to the host. */
+
+ if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) {
+ log_full_errno(prio, errno, "Failed to remount root directory as MS_SLAVE: %m");
+ _exit(EXIT_FAILURE);
+ }
+ }
+
if (flags & FORK_CLOSE_ALL_FDS) {
/* Close the logs here in case it got reopened above, as close_all_fds() would close them for us */
log_close();
diff --git a/src/systemd/src/basic/process-util.h b/src/systemd/src/basic/process-util.h
index e3bf36bf04..e11164bd82 100644
--- a/src/systemd/src/basic/process-util.h
+++ b/src/systemd/src/basic/process-util.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
-
#include <alloca.h>
#include <errno.h>
#include <sched.h>
@@ -51,8 +45,8 @@ int get_process_ppid(pid_t pid, pid_t *ppid);
int wait_for_terminate(pid_t pid, siginfo_t *status);
typedef enum WaitFlags {
- WAIT_LOG_ABNORMAL = 1U << 0,
- WAIT_LOG_NON_ZERO_EXIT_STATUS = 1U << 1,
+ WAIT_LOG_ABNORMAL = 1 << 0,
+ WAIT_LOG_NON_ZERO_EXIT_STATUS = 1 << 1,
/* A shortcut for requesting the most complete logging */
WAIT_LOG = WAIT_LOG_ABNORMAL|WAIT_LOG_NON_ZERO_EXIT_STATUS,
@@ -157,14 +151,15 @@ void reset_cached_pid(void);
int must_be_root(void);
typedef enum ForkFlags {
- FORK_RESET_SIGNALS = 1U << 0,
- FORK_CLOSE_ALL_FDS = 1U << 1,
- FORK_DEATHSIG = 1U << 2,
- FORK_NULL_STDIO = 1U << 3,
- FORK_REOPEN_LOG = 1U << 4,
- FORK_LOG = 1U << 5,
- FORK_WAIT = 1U << 6,
- FORK_NEW_MOUNTNS = 1U << 7,
+ FORK_RESET_SIGNALS = 1 << 0,
+ FORK_CLOSE_ALL_FDS = 1 << 1,
+ FORK_DEATHSIG = 1 << 2,
+ FORK_NULL_STDIO = 1 << 3,
+ FORK_REOPEN_LOG = 1 << 4,
+ FORK_LOG = 1 << 5,
+ FORK_WAIT = 1 << 6,
+ FORK_NEW_MOUNTNS = 1 << 7,
+ FORK_MOUNTNS_SLAVE = 1 << 8,
} ForkFlags;
int safe_fork_full(const char *name, const int except_fds[], size_t n_except_fds, ForkFlags flags, pid_t *ret_pid);
diff --git a/src/systemd/src/basic/random-util.c b/src/systemd/src/basic/random-util.c
index d80751cfe9..01a8488f88 100644
--- a/src/systemd/src/basic/random-util.c
+++ b/src/systemd/src/basic/random-util.c
@@ -1,9 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
#include "nm-sd-adapt.h"
@@ -48,9 +43,9 @@ int acquire_random_bytes(void *p, size_t n, bool high_quality_required) {
* for us. */
/* Use the getrandom() syscall unless we know we don't have it. */
- if (have_syscall != 0) {
+ if (have_syscall != 0 && !HAS_FEATURE_MEMORY_SANITIZER) {
#if !HAVE_GETRANDOM
- /* XXX: NM: systemd calls the syscall directly in this case. Don't add that workaround.
+ /* NetworkManager Note: systemd calls the syscall directly in this case. Don't add that workaround.
* If you don't compile against a libc that provides getrandom(), you don't get it. */
r = -1;
errno = ENOSYS;
diff --git a/src/systemd/src/basic/random-util.h b/src/systemd/src/basic/random-util.h
index 723917057d..9a103f0e94 100644
--- a/src/systemd/src/basic/random-util.h
+++ b/src/systemd/src/basic/random-util.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
-
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
diff --git a/src/systemd/src/basic/refcnt.h b/src/systemd/src/basic/refcnt.h
index 0d5b3f4e1b..d2be6086d2 100644
--- a/src/systemd/src/basic/refcnt.h
+++ b/src/systemd/src/basic/refcnt.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-***/
-
/* A type-safe atomic refcounter.
*
* DO NOT USE THIS UNLESS YOU ACTUALLY CARE ABOUT THREAD SAFETY! */
diff --git a/src/systemd/src/basic/set.h b/src/systemd/src/basic/set.h
index dc0f1e17e6..664713810d 100644
--- a/src/systemd/src/basic/set.h
+++ b/src/systemd/src/basic/set.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
-
#include "extract-word.h"
#include "hashmap.h"
#include "macro.h"
diff --git a/src/systemd/src/basic/signal-util.h b/src/systemd/src/basic/signal-util.h
index 0c43467b63..92f2804cd2 100644
--- a/src/systemd/src/basic/signal-util.h
+++ b/src/systemd/src/basic/signal-util.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010-2015 Lennart Poettering
-***/
-
#include <signal.h>
#include "macro.h"
diff --git a/src/systemd/src/basic/socket-util.c b/src/systemd/src/basic/socket-util.c
index aa06070e6b..a71db5a7ea 100644
--- a/src/systemd/src/basic/socket-util.c
+++ b/src/systemd/src/basic/socket-util.c
@@ -1,9 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
#include "nm-sd-adapt.h"
@@ -793,7 +788,7 @@ static const char* const socket_address_bind_ipv6_only_table[_SOCKET_ADDRESS_BIN
DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
-SocketAddressBindIPv6Only parse_socket_address_bind_ipv6_only_or_bool(const char *n) {
+SocketAddressBindIPv6Only socket_address_bind_ipv6_only_or_bool_from_string(const char *n) {
int r;
r = parse_boolean(n);
diff --git a/src/systemd/src/basic/socket-util.h b/src/systemd/src/basic/socket-util.h
index c2d21b45c4..e2db795ae6 100644
--- a/src/systemd/src/basic/socket-util.h
+++ b/src/systemd/src/basic/socket-util.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
-
#include <netinet/ether.h>
#include <netinet/in.h>
#include <stdbool.h>
@@ -118,7 +112,7 @@ int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret);
const char* socket_address_bind_ipv6_only_to_string(SocketAddressBindIPv6Only b) _const_;
SocketAddressBindIPv6Only socket_address_bind_ipv6_only_from_string(const char *s) _pure_;
-SocketAddressBindIPv6Only parse_socket_address_bind_ipv6_only_or_bool(const char *s);
+SocketAddressBindIPv6Only socket_address_bind_ipv6_only_or_bool_from_string(const char *s);
int netlink_family_to_string_alloc(int b, char **s);
int netlink_family_from_string(const char *s) _pure_;
diff --git a/src/systemd/src/basic/stat-util.c b/src/systemd/src/basic/stat-util.c
index 28e75618bc..9892d8bc5c 100644
--- a/src/systemd/src/basic/stat-util.c
+++ b/src/systemd/src/basic/stat-util.c
@@ -1,9 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010-2012 Lennart Poettering
-***/
#include "nm-sd-adapt.h"
@@ -135,32 +130,6 @@ int path_is_read_only_fs(const char *path) {
return false;
}
-int path_is_os_tree(const char *path) {
- int r;
-
- assert(path);
-
- /* Does the path exist at all? If not, generate an error immediately. This is useful so that a missing root dir
- * always results in -ENOENT, and we can properly distuingish the case where the whole root doesn't exist from
- * the case where just the os-release file is missing. */
- if (laccess(path, F_OK) < 0)
- return -errno;
-
- /* We use /usr/lib/os-release as flag file if something is an OS */
- r = chase_symlinks("/usr/lib/os-release", path, CHASE_PREFIX_ROOT, NULL);
- if (r == -ENOENT) {
-
- /* Also check for the old location in /etc, just in case. */
- r = chase_symlinks("/etc/os-release", path, CHASE_PREFIX_ROOT, NULL);
- if (r == -ENOENT)
- return 0; /* We got nothing */
- }
- if (r < 0)
- return r;
-
- return 1;
-}
-
int files_same(const char *filea, const char *fileb, int flags) {
struct stat a, b;
diff --git a/src/systemd/src/basic/stat-util.h b/src/systemd/src/basic/stat-util.h
index d1e8d33001..f8014ed30b 100644
--- a/src/systemd/src/basic/stat-util.h
+++ b/src/systemd/src/basic/stat-util.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010-2012 Lennart Poettering
-***/
-
#include <stdbool.h>
#include <stddef.h>
#include <sys/stat.h>
@@ -35,7 +29,6 @@ int null_or_empty_path(const char *fn);
int null_or_empty_fd(int fd);
int path_is_read_only_fs(const char *path);
-int path_is_os_tree(const char *path);
int files_same(const char *filea, const char *fileb, int flags);
diff --git a/src/systemd/src/basic/stdio-util.h b/src/systemd/src/basic/stdio-util.h
index 5330789aaa..73c03274c7 100644
--- a/src/systemd/src/basic/stdio-util.h
+++ b/src/systemd/src/basic/stdio-util.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
-
#include <printf.h>
#include <stdarg.h>
#include <stdio.h>
diff --git a/src/systemd/src/basic/string-table.c b/src/systemd/src/basic/string-table.c
index 34723b4c2e..94412ed2b4 100644
--- a/src/systemd/src/basic/string-table.c
+++ b/src/systemd/src/basic/string-table.c
@@ -1,9 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
#include "nm-sd-adapt.h"
diff --git a/src/systemd/src/basic/string-table.h b/src/systemd/src/basic/string-table.h
index a39206fb94..9bd7879355 100644
--- a/src/systemd/src/basic/string-table.h
+++ b/src/systemd/src/basic/string-table.h
@@ -2,12 +2,6 @@
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
-
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
@@ -77,7 +71,6 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k
return (type) -1; \
} \
-
#define _DEFINE_STRING_TABLE_LOOKUP(name,type,scope) \
_DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \
_DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope)
@@ -102,3 +95,18 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k
_DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,static)
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max) \
_DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,static)
+
+#define DUMP_STRING_TABLE(name,type,max) \
+ do { \
+ type _k; \
+ flockfile(stdout); \
+ for (_k = 0; _k < (max); _k++) { \
+ const char *_t; \
+ _t = name##_to_string(_k); \
+ if (!_t) \
+ continue; \
+ fputs_unlocked(_t, stdout); \
+ fputc_unlocked('\n', stdout); \
+ } \
+ funlockfile(stdout); \
+ } while(false)
diff --git a/src/systemd/src/basic/string-util.c b/src/systemd/src/basic/string-util.c
index a60c7dccfe..1747f35b25 100644
--- a/src/systemd/src/basic/string-util.c
+++ b/src/systemd/src/basic/string-util.c
@@ -1,9 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
#include "nm-sd-adapt.h"
@@ -16,6 +11,7 @@
#include <string.h>
#include "alloc-util.h"
+#include "escape.h"
#include "gunicode.h"
#include "locale-util.h"
#include "macro.h"
@@ -271,23 +267,12 @@ char *strjoin_real(const char *x, ...) {
}
char *strstrip(char *s) {
- char *e;
-
if (!s)
return NULL;
- /* Drops trailing whitespace. Modifies the string in
- * place. Returns pointer to first non-space character */
-
- s += strspn(s, WHITESPACE);
-
- for (e = strchr(s, 0); e > s; e --)
- if (!strchr(WHITESPACE, e[-1]))
- break;
-
- *e = 0;
+ /* Drops trailing whitespace. Modifies the string in place. Returns pointer to first non-space character */
- return s;
+ return delete_trailing_chars(skip_leading_chars(s, WHITESPACE), WHITESPACE);
}
char *delete_chars(char *s, const char *bad) {
@@ -458,9 +443,23 @@ bool string_has_cc(const char *p, const char *ok) {
}
#if 0 /* NM_IGNORED */
+static int write_ellipsis(char *buf, bool unicode) {
+ if (unicode || is_locale_utf8()) {
+ buf[0] = 0xe2; /* tri-dot ellipsis: … */
+ buf[1] = 0x80;
+ buf[2] = 0xa6;
+ } else {
+ buf[0] = '.';
+ buf[1] = '.';
+ buf[2] = '.';
+ }
+
+ return 3;
+}
+
static char *ascii_ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
- size_t x, need_space;
- char *r;
+ size_t x, need_space, suffix_len;
+ char *t;
assert(s);
assert(percent <= 100);
@@ -496,8 +495,8 @@ static char *ascii_ellipsize_mem(const char *s, size_t old_length, size_t new_le
* either for the UTF-8 encoded character or for three ASCII characters. */
need_space = is_locale_utf8() ? 1 : 3;
- r = new(char, new_length+3);
- if (!r)
+ t = new(char, new_length+3);
+ if (!t)
return NULL;
assert(new_length >= need_space);
@@ -505,23 +504,13 @@ static char *ascii_ellipsize_mem(const char *s, size_t old_length, size_t new_le
x = ((new_length - need_space) * percent + 50) / 100;
assert(x <= new_length - need_space);
- memcpy(r, s, x);
-
- if (is_locale_utf8()) {
- r[x+0] = 0xe2; /* tri-dot ellipsis: … */
- r[x+1] = 0x80;
- r[x+2] = 0xa6;
- } else {
- r[x+0] = '.';
- r[x+1] = '.';
- r[x+2] = '.';
- }
-
- memcpy(r + x + 3,
- s + old_length - (new_length - x - need_space),
- new_length - x - need_space + 1);
+ memcpy(t, s, x);
+ write_ellipsis(t + x, false);
+ suffix_len = new_length - x - need_space;
+ memcpy(t + x + 3, s + old_length - suffix_len, suffix_len);
+ *(t + x + 3 + suffix_len) = '\0';
- return r;
+ return t;
}
char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
@@ -552,42 +541,56 @@ char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigne
return strdup("");
/* If no multibyte characters use ascii_ellipsize_mem for speed */
- if (ascii_is_valid(s))
+ if (ascii_is_valid_n(s, old_length))
return ascii_ellipsize_mem(s, old_length, new_length, percent);
x = ((new_length - 1) * percent) / 100;
assert(x <= new_length - 1);
k = 0;
- for (i = s; k < x && i < s + old_length; i = utf8_next_char(i)) {
+ for (i = s; i < s + old_length; i = utf8_next_char(i)) {
char32_t c;
+ int w;
r = utf8_encoded_to_unichar(i, &c);
if (r < 0)
return NULL;
- k += unichar_iswide(c) ? 2 : 1;
- }
- if (k > x) /* last character was wide and went over quota */
- x++;
+ w = unichar_iswide(c) ? 2 : 1;
+ if (k + w <= x)
+ k += w;
+ else
+ break;
+ }
- for (j = s + old_length; k < new_length && j > i; ) {
+ for (j = s + old_length; j > i; ) {
char32_t c;
+ int w;
+ const char *jj;
- j = utf8_prev_char(j);
- r = utf8_encoded_to_unichar(j, &c);
+ jj = utf8_prev_char(j);
+ r = utf8_encoded_to_unichar(jj, &c);
if (r < 0)
return NULL;
- k += unichar_iswide(c) ? 2 : 1;
+
+ w = unichar_iswide(c) ? 2 : 1;
+ if (k + w <= new_length) {
+ k += w;
+ j = jj;
+ } else
+ break;
}
assert(i <= j);
/* we don't actually need to ellipsize */
if (i == j)
- return memdup(s, old_length + 1);
+ return memdup_suffix0(s, old_length);
- /* make space for ellipsis */
- j = utf8_next_char(j);
+ /* make space for ellipsis, if possible */
+ if (j < s + old_length)
+ j = utf8_next_char(j);
+ else if (i > s)
+ i = utf8_prev_char(i);
len = i - s;
len2 = s + old_length - j;
@@ -601,21 +604,81 @@ char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigne
*/
memcpy(e, s, len);
- e[len + 0] = 0xe2; /* tri-dot ellipsis: … */
- e[len + 1] = 0x80;
- e[len + 2] = 0xa6;
-
- memcpy(e + len + 3, j, len2 + 1);
+ write_ellipsis(e + len, true);
+ memcpy(e + len + 3, j, len2);
+ *(e + len + 3 + len2) = '\0';
return e;
}
-char *ellipsize(const char *s, size_t length, unsigned percent) {
+char *cellescape(char *buf, size_t len, const char *s) {
+ /* Escape and ellipsize s into buffer buf of size len. Only non-control ASCII
+ * characters are copied as they are, everything else is escaped. The result
+ * is different then if escaping and ellipsization was performed in two
+ * separate steps, because each sequence is either stored in full or skipped.
+ *
+ * This function should be used for logging about strings which expected to
+ * be plain ASCII in a safe way.
+ *
+ * An ellipsis will be used if s is too long. It was always placed at the
+ * very end.
+ */
- if (length == (size_t) -1)
- return strdup(s);
+ size_t i = 0, last_char_width[4] = {}, k = 0, j;
+
+ assert(len > 0); /* at least a terminating NUL */
+
+ for (;;) {
+ char four[4];
+ int w;
+
+ if (*s == 0) /* terminating NUL detected? then we are done! */
+ goto done;
+
+ w = cescape_char(*s, four);
+ if (i + w + 1 > len) /* This character doesn't fit into the buffer anymore? In that case let's
+ * ellipsize at the previous location */
+ break;
+
+ /* OK, there was space, let's add this escaped character to the buffer */
+ memcpy(buf + i, four, w);
+ i += w;
+
+ /* And remember its width in the ring buffer */
+ last_char_width[k] = w;
+ k = (k + 1) % 4;
+
+ s++;
+ }
+
+ /* Ellipsation is necessary. This means we might need to truncate the string again to make space for 4
+ * characters ideally, but the buffer is shorter than that in the first place take what we can get */
+ for (j = 0; j < ELEMENTSOF(last_char_width); j++) {
+
+ if (i + 4 <= len) /* nice, we reached our space goal */
+ break;
+
+ k = k == 0 ? 3 : k - 1;
+ if (last_char_width[k] == 0) /* bummer, we reached the beginning of the strings */
+ break;
+
+ assert(i >= last_char_width[k]);
+ i -= last_char_width[k];
+ }
+
+ if (i + 4 <= len) /* yay, enough space */
+ i += write_ellipsis(buf + i, false);
+ else if (i + 3 <= len) { /* only space for ".." */
+ buf[i++] = '.';
+ buf[i++] = '.';
+ } else if (i + 2 <= len) /* only space for a single "." */
+ buf[i++] = '.';
+ else
+ assert(i + 1 <= len);
- return ellipsize_mem(s, strlen(s), length, percent);
+ done:
+ buf[i] = '\0';
+ return buf;
}
#endif /* NM_IGNORED */
diff --git a/src/systemd/src/basic/string-util.h b/src/systemd/src/basic/string-util.h
index 5a10eeabfe..c0cc4e78d7 100644
--- a/src/systemd/src/basic/string-util.h
+++ b/src/systemd/src/basic/string-util.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
-
#include <alloca.h>
#include <stdbool.h>
#include <stddef.h>
@@ -156,7 +150,14 @@ static inline bool _pure_ in_charset(const char *s, const char* charset) {
bool string_has_cc(const char *p, const char *ok) _pure_;
char *ellipsize_mem(const char *s, size_t old_length_bytes, size_t new_length_columns, unsigned percent);
-char *ellipsize(const char *s, size_t length, unsigned percent);
+static inline char *ellipsize(const char *s, size_t length, unsigned percent) {
+ return ellipsize_mem(s, strlen(s), length, percent);
+}
+
+char *cellescape(char *buf, size_t len, const char *s);
+
+/* This limit is arbitrary, enough to give some idea what the string contains */
+#define CELLESCAPE_DEFAULT_LENGTH 64
bool nulstr_contains(const char *nulstr, const char *needle);
@@ -209,3 +210,21 @@ static inline size_t strlen_ptr(const char *s) {
return strlen(s);
}
+
+/* Like startswith(), but operates on arbitrary memory blocks */
+static inline void *memory_startswith(const void *p, size_t sz, const char *token) {
+ size_t n;
+
+ assert(token);
+
+ n = strlen(token);
+ if (sz < n)
+ return NULL;
+
+ assert(p);
+
+ if (memcmp(p, token, n) != 0)
+ return NULL;
+
+ return (uint8_t*) p + n;
+}
diff --git a/src/systemd/src/basic/strv.c b/src/systemd/src/basic/strv.c
index 9d5000aac1..9da8ceceb7 100644
--- a/src/systemd/src/basic/strv.c
+++ b/src/systemd/src/basic/strv.c
@@ -1,9 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
#include "nm-sd-adapt.h"
diff --git a/src/systemd/src/basic/strv.h b/src/systemd/src/basic/strv.h
index 958c5f3a98..51d03db940 100644
--- a/src/systemd/src/basic/strv.h
+++ b/src/systemd/src/basic/strv.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
-
#include <fnmatch.h>
#include <stdarg.h>
#include <stdbool.h>
diff --git a/src/systemd/src/basic/time-util.c b/src/systemd/src/basic/time-util.c
index fa9f66f2ae..aafa03757a 100644
--- a/src/systemd/src/basic/time-util.c
+++ b/src/systemd/src/basic/time-util.c
@@ -1,9 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
#include "nm-sd-adapt.h"
@@ -285,8 +280,11 @@ static char *format_timestamp_internal(
return NULL; /* Timestamp is unset */
/* Let's not format times with years > 9999 */
- if (t > USEC_TIMESTAMP_FORMATTABLE_MAX)
- return NULL;
+ if (t > USEC_TIMESTAMP_FORMATTABLE_MAX) {
+ assert(l >= strlen("--- XXXX-XX-XX XX:XX:XX") + 1);
+ strcpy(buf, "--- XXXX-XX-XX XX:XX:XX");
+ return buf;
+ }
sec = (time_t) (t / USEC_PER_SEC); /* Round down */
@@ -485,7 +483,7 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
/* Let's see if we should shows this in dot notation */
if (t < USEC_PER_MINUTE && b > 0) {
usec_t cc;
- int j;
+ signed char j;
j = 0;
for (cc = table[i].usec; cc > 1; cc /= 10)
@@ -1314,6 +1312,9 @@ bool timezone_is_valid(const char *name, int log_level) {
if (slash)
return false;
+ if (p - name >= PATH_MAX)
+ return false;
+
t = strjoina("/usr/share/zoneinfo/", name);
fd = open(t, O_RDONLY|O_CLOEXEC);
@@ -1467,4 +1468,28 @@ bool in_utc_timezone(void) {
return timezone == 0 && daylight == 0;
}
+
+int time_change_fd(void) {
+
+ /* We only care for the cancellation event, hence we set the timeout to the latest possible value. */
+ static const struct itimerspec its = {
+ .it_value.tv_sec = TIME_T_MAX,
+ };
+
+ _cleanup_close_ int fd;
+
+ assert_cc(sizeof(time_t) == sizeof(TIME_T_MAX));
+
+ /* Uses TFD_TIMER_CANCEL_ON_SET to get notifications whenever CLOCK_REALTIME makes a jump relative to
+ * CLOCK_MONOTONIC. */
+
+ fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC);
+ if (fd < 0)
+ return -errno;
+
+ if (timerfd_settime(fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &its, NULL) < 0)
+ return -errno;
+
+ return TAKE_FD(fd);
+}
#endif /* NM_IGNORED */
diff --git a/src/systemd/src/basic/time-util.h b/src/systemd/src/basic/time-util.h
index e720688c2b..344f2dc52e 100644
--- a/src/systemd/src/basic/time-util.h
+++ b/src/systemd/src/basic/time-util.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
-
#include <inttypes.h>
#include <stdbool.h>
#include <stddef.h>
@@ -183,5 +177,7 @@ static inline usec_t usec_sub_signed(usec_t timestamp, int64_t delta) {
/* With a 32bit time_t we can't go beyond 2038... */
#define USEC_TIMESTAMP_FORMATTABLE_MAX ((usec_t) 2147483647000000)
#else
-#error "Yuck, time_t is neither 4 not 8 bytes wide?"
+#error "Yuck, time_t is neither 4 nor 8 bytes wide?"
#endif
+
+int time_change_fd(void);
diff --git a/src/systemd/src/basic/umask-util.h b/src/systemd/src/basic/umask-util.h
index ce705247d6..e964292eaf 100644
--- a/src/systemd/src/basic/umask-util.h
+++ b/src/systemd/src/basic/umask-util.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
-
#include <stdbool.h>
#include <sys/stat.h>
#include <sys/types.h>
diff --git a/src/systemd/src/basic/utf8.c b/src/systemd/src/basic/utf8.c
index 7a382204f2..80de43c572 100644
--- a/src/systemd/src/basic/utf8.c
+++ b/src/systemd/src/basic/utf8.c
@@ -1,9 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2008-2011 Kay Sievers
- Copyright 2012 Lennart Poettering
+ Copyright © 2008-2011 Kay Sievers
***/
/* Parts of this file are based on the GLIB utf8 validation functions. The
@@ -249,6 +246,9 @@ char *utf8_escape_non_printable(const char *str) {
char *ascii_is_valid(const char *str) {
const char *p;
+ /* Check whether the string consists of valid ASCII bytes,
+ * i.e values between 0 and 127, inclusive. */
+
assert(str);
for (p = str; *p; p++)
@@ -258,6 +258,21 @@ char *ascii_is_valid(const char *str) {
return (char*) str;
}
+char *ascii_is_valid_n(const char *str, size_t len) {
+ size_t i;
+
+ /* Very similar to ascii_is_valid(), but checks exactly len
+ * bytes and rejects any NULs in that range. */
+
+ assert(str);
+
+ for (i = 0; i < len; i++)
+ if ((unsigned char) str[i] >= 128 || str[i] == 0)
+ return NULL;
+
+ return (char*) str;
+}
+
/**
* utf8_encode_unichar() - Encode single UCS-4 character as UTF-8
* @out_utf8: output buffer of at least 4 bytes or NULL
diff --git a/src/systemd/src/basic/utf8.h b/src/systemd/src/basic/utf8.h
index 0ebe36d96b..f37f87ffe6 100644
--- a/src/systemd/src/basic/utf8.h
+++ b/src/systemd/src/basic/utf8.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-***/
-
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
@@ -24,6 +18,7 @@ bool unichar_is_valid(char32_t c);
const char *utf8_is_valid(const char *s) _pure_;
char *ascii_is_valid(const char *s) _pure_;
+char *ascii_is_valid_n(const char *str, size_t len);
bool utf8_is_printable_newline(const char* str, size_t length, bool newline) _pure_;
#define utf8_is_printable(str, length) utf8_is_printable_newline(str, length, true)
diff --git a/src/systemd/src/basic/util.c b/src/systemd/src/basic/util.c
index 12e2f45115..ba7474f0bb 100644
--- a/src/systemd/src/basic/util.c
+++ b/src/systemd/src/basic/util.c
@@ -1,9 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
#include "nm-sd-adapt.h"
@@ -269,7 +264,7 @@ int container_get_leader(const char *machine, pid_t *pid) {
return -EINVAL;
p = strjoina("/run/systemd/machines/", machine);
- r = parse_env_file(p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL);
+ r = parse_env_file(NULL, p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL);
if (r == -ENOENT)
return -EHOSTDOWN;
if (r < 0)
@@ -410,6 +405,7 @@ uint64_t physical_memory(void) {
uint64_t mem, lim;
size_t ps;
long sc;
+ int r;
/* We return this as uint64_t in case we are running as 32bit process on a 64bit kernel with huge amounts of
* memory.
@@ -423,13 +419,40 @@ uint64_t physical_memory(void) {
ps = page_size();
mem = (uint64_t) sc * (uint64_t) ps;
- if (cg_get_root_path(&root) < 0)
+ r = cg_get_root_path(&root);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to determine root cgroup, ignoring cgroup memory limit: %m");
return mem;
+ }
- if (cg_get_attribute("memory", root, "memory.limit_in_bytes", &value))
+ r = cg_all_unified();
+ if (r < 0) {
+ log_debug_errno(r, "Failed to determine root unified mode, ignoring cgroup memory limit: %m");
return mem;
+ }
+ if (r > 0) {
+ r = cg_get_attribute("memory", root, "memory.max", &value);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to read memory.max cgroup attribute, ignoring cgroup memory limit: %m");
+ return mem;
+ }
+
+ if (streq(value, "max"))
+ return mem;
+ } else {
+ r = cg_get_attribute("memory", root, "memory.limit_in_bytes", &value);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to read memory.limit_in_bytes cgroup attribute, ignoring cgroup memory limit: %m");
+ return mem;
+ }
+ }
- if (safe_atou64(value, &lim) < 0)
+ r = safe_atou64(value, &lim);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to parse cgroup memory limit '%s', ignoring: %m", value);
+ return mem;
+ }
+ if (lim == UINT64_MAX)
return mem;
/* Make sure the limit is a multiple of our own page size */
@@ -470,6 +493,7 @@ uint64_t system_tasks_max(void) {
uint64_t a = TASKS_MAX, b = TASKS_MAX;
_cleanup_free_ char *root = NULL;
+ int r;
/* Determine the maximum number of tasks that may run on this system. We check three sources to determine this
* limit:
@@ -480,13 +504,24 @@ uint64_t system_tasks_max(void) {
*
* And then pick the smallest of the three */
- (void) procfs_tasks_get_limit(&a);
+ r = procfs_tasks_get_limit(&a);
+ if (r < 0)
+ log_debug_errno(r, "Failed to read maximum number of tasks from /proc, ignoring: %m");
- if (cg_get_root_path(&root) >= 0) {
+ r = cg_get_root_path(&root);
+ if (r < 0)
+ log_debug_errno(r, "Failed to determine cgroup root path, ignoring: %m");
+ else {
_cleanup_free_ char *value = NULL;
- if (cg_get_attribute("pids", root, "pids.max", &value) >= 0)
- (void) safe_atou64(value, &b);
+ r = cg_get_attribute("pids", root, "pids.max", &value);
+ if (r < 0)
+ log_debug_errno(r, "Failed to read pids.max attribute of cgroup root, ignoring: %m");
+ else if (!streq(value, "max")) {
+ r = safe_atou64(value, &b);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse pids.max attribute of cgroup root, ignoring: %m");
+ }
}
return MIN3(TASKS_MAX,
diff --git a/src/systemd/src/basic/util.h b/src/systemd/src/basic/util.h
index ad1931f7b6..9699d228f9 100644
--- a/src/systemd/src/basic/util.h
+++ b/src/systemd/src/basic/util.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-***/
-
#include <alloca.h>
#include <errno.h>
#include <fcntl.h>
diff --git a/src/systemd/src/libsystemd-network/arp-util.c b/src/systemd/src/libsystemd-network/arp-util.c
index 26db7ea871..1b711c950d 100644
--- a/src/systemd/src/libsystemd-network/arp-util.c
+++ b/src/systemd/src/libsystemd-network/arp-util.c
@@ -1,9 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Axis Communications AB. All rights reserved.
- Copyright (C) 2015 Tom Gundersen
+ Copyright © 2014 Axis Communications AB. All rights reserved.
+ Copyright © 2015 Tom Gundersen
***/
#include "nm-sd-adapt.h"
diff --git a/src/systemd/src/libsystemd-network/arp-util.h b/src/systemd/src/libsystemd-network/arp-util.h
index 86864e9fd5..10c684864b 100644
--- a/src/systemd/src/libsystemd-network/arp-util.h
+++ b/src/systemd/src/libsystemd-network/arp-util.h
@@ -2,9 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Axis Communications AB. All rights reserved.
+ Copyright © 2014 Axis Communications AB. All rights reserved.
***/
#include <netinet/if_ether.h>
diff --git a/src/systemd/src/libsystemd-network/dhcp-identifier.c b/src/systemd/src/libsystemd-network/dhcp-identifier.c
index 6f8adfa610..753573676c 100644
--- a/src/systemd/src/libsystemd-network/dhcp-identifier.c
+++ b/src/systemd/src/libsystemd-network/dhcp-identifier.c
@@ -1,8 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2015 Tom Gundersen <teg@jklmen>
+ Copyright © 2015 Tom Gundersen <teg@jklmen>
***/
#include "nm-sd-adapt.h"
diff --git a/src/systemd/src/libsystemd-network/dhcp-identifier.h b/src/systemd/src/libsystemd-network/dhcp-identifier.h
index c0a10b6c35..42d4956d10 100644
--- a/src/systemd/src/libsystemd-network/dhcp-identifier.h
+++ b/src/systemd/src/libsystemd-network/dhcp-identifier.h
@@ -2,9 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright (C) 2015 Tom Gundersen <teg@jklmen>
+ Copyright © 2015 Tom Gundersen <teg@jklmen>
***/
#include "sd-id128.h"
diff --git a/src/systemd/src/libsystemd-network/dhcp-internal.h b/src/systemd/src/libsystemd-network/dhcp-internal.h
index f827622233..257a3c2e2f 100644
--- a/src/systemd/src/libsystemd-network/dhcp-internal.h
+++ b/src/systemd/src/libsystemd-network/dhcp-internal.h
@@ -2,10 +2,8 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
- Copyright (C) 2014 Tom Gundersen
+ Copyright © 2013 Intel Corporation. All rights reserved.
+ Copyright © 2014 Tom Gundersen
***/
#include <linux/if_packet.h>
diff --git a/src/systemd/src/libsystemd-network/dhcp-lease-internal.h b/src/systemd/src/libsystemd-network/dhcp-lease-internal.h
index 66c213e28c..fabac183ef 100644
--- a/src/systemd/src/libsystemd-network/dhcp-lease-internal.h
+++ b/src/systemd/src/libsystemd-network/dhcp-lease-internal.h
@@ -2,10 +2,8 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
- Copyright (C) 2014 Tom Gundersen
+ Copyright © 2013 Intel Corporation. All rights reserved.
+ Copyright © 2014 Tom Gundersen
***/
#include <stdint.h>
diff --git a/src/systemd/src/libsystemd-network/dhcp-network.c b/src/systemd/src/libsystemd-network/dhcp-network.c
index 37c1ba193d..90fe29d046 100644
--- a/src/systemd/src/libsystemd-network/dhcp-network.c
+++ b/src/systemd/src/libsystemd-network/dhcp-network.c
@@ -1,8 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
+ Copyright © 2013 Intel Corporation. All rights reserved.
***/
#include "nm-sd-adapt.h"
diff --git a/src/systemd/src/libsystemd-network/dhcp-option.c b/src/systemd/src/libsystemd-network/dhcp-option.c
index 86e67358c3..4a4f7de020 100644
--- a/src/systemd/src/libsystemd-network/dhcp-option.c
+++ b/src/systemd/src/libsystemd-network/dhcp-option.c
@@ -1,8 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
+ Copyright © 2013 Intel Corporation. All rights reserved.
***/
#include "nm-sd-adapt.h"
diff --git a/src/systemd/src/libsystemd-network/dhcp-packet.c b/src/systemd/src/libsystemd-network/dhcp-packet.c
index 136bab9d60..214aed8e82 100644
--- a/src/systemd/src/libsystemd-network/dhcp-packet.c
+++ b/src/systemd/src/libsystemd-network/dhcp-packet.c
@@ -1,9 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
- Copyright (C) 2014 Tom Gundersen
+ Copyright © 2013 Intel Corporation. All rights reserved.
+ Copyright © 2014 Tom Gundersen
***/
#include "nm-sd-adapt.h"
diff --git a/src/systemd/src/libsystemd-network/dhcp-protocol.h b/src/systemd/src/libsystemd-network/dhcp-protocol.h
index 2230e094d0..f03663248a 100644
--- a/src/systemd/src/libsystemd-network/dhcp-protocol.h
+++ b/src/systemd/src/libsystemd-network/dhcp-protocol.h
@@ -2,9 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
+ Copyright © 2013 Intel Corporation. All rights reserved.
***/
#include <netinet/ip.h>
diff --git a/src/systemd/src/libsystemd-network/dhcp6-internal.h b/src/systemd/src/libsystemd-network/dhcp6-internal.h
index 33c4332081..f1cbd6a4f1 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-internal.h
+++ b/src/systemd/src/libsystemd-network/dhcp6-internal.h
@@ -2,9 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
+ Copyright © 2014-2015 Intel Corporation. All rights reserved.
***/
#include <net/ethernet.h>
diff --git a/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h b/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h
index 2bf5499770..dc85c437c9 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h
+++ b/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h
@@ -2,10 +2,8 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Tom Gundersen
- Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
+ Copyright © 2014 Tom Gundersen
+ Copyright © 2014-2015 Intel Corporation. All rights reserved.
***/
#include <stdint.h>
diff --git a/src/systemd/src/libsystemd-network/dhcp6-network.c b/src/systemd/src/libsystemd-network/dhcp6-network.c
index 2c6dc7131d..98aa6261eb 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-network.c
+++ b/src/systemd/src/libsystemd-network/dhcp6-network.c
@@ -1,8 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Intel Corporation. All rights reserved.
+ Copyright © 2014 Intel Corporation. All rights reserved.
***/
#include "nm-sd-adapt.h"
diff --git a/src/systemd/src/libsystemd-network/dhcp6-option.c b/src/systemd/src/libsystemd-network/dhcp6-option.c
index 87ae96a203..a8a56463a5 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-option.c
+++ b/src/systemd/src/libsystemd-network/dhcp6-option.c
@@ -1,8 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
+ Copyright © 2014-2015 Intel Corporation. All rights reserved.
***/
#include "nm-sd-adapt.h"
@@ -143,7 +141,7 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) {
}
int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn) {
- uint8_t buffer[1 + DNS_WIRE_FOMAT_HOSTNAME_MAX];
+ uint8_t buffer[1 + DNS_WIRE_FORMAT_HOSTNAME_MAX];
int r;
assert_return(buf && *buf && buflen && fqdn, -EINVAL);
diff --git a/src/systemd/src/libsystemd-network/dhcp6-protocol.h b/src/systemd/src/libsystemd-network/dhcp6-protocol.h
index 18417062d3..ffae4453ac 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-protocol.h
+++ b/src/systemd/src/libsystemd-network/dhcp6-protocol.h
@@ -2,9 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Intel Corporation. All rights reserved.
+ Copyright © 2014 Intel Corporation. All rights reserved.
***/
#include <netinet/ip6.h>
diff --git a/src/systemd/src/libsystemd-network/lldp-internal.h b/src/systemd/src/libsystemd-network/lldp-internal.h
index 06cf7e8dad..e56509884e 100644
--- a/src/systemd/src/libsystemd-network/lldp-internal.h
+++ b/src/systemd/src/libsystemd-network/lldp-internal.h
@@ -2,10 +2,8 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Tom Gundersen
- Copyright (C) 2014 Susant Sahani
+ Copyright © 2014 Tom Gundersen
+ Copyright © 2014 Susant Sahani
***/
#include "sd-event.h"
diff --git a/src/systemd/src/libsystemd-network/lldp-neighbor.c b/src/systemd/src/libsystemd-network/lldp-neighbor.c
index 373e34c8eb..c28c995637 100644
--- a/src/systemd/src/libsystemd-network/lldp-neighbor.c
+++ b/src/systemd/src/libsystemd-network/lldp-neighbor.c
@@ -1,9 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-***/
#include "nm-sd-adapt.h"
diff --git a/src/systemd/src/libsystemd-network/lldp-neighbor.h b/src/systemd/src/libsystemd-network/lldp-neighbor.h
index fae49c590f..494bc51760 100644
--- a/src/systemd/src/libsystemd-network/lldp-neighbor.h
+++ b/src/systemd/src/libsystemd-network/lldp-neighbor.h
@@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-***/
-
#include <inttypes.h>
#include <stdbool.h>
#include <sys/types.h>
diff --git a/src/systemd/src/libsystemd-network/lldp-network.c b/src/systemd/src/libsystemd-network/lldp-network.c
index 307cf6c394..bc6c20d1fd 100644
--- a/src/systemd/src/libsystemd-network/lldp-network.c
+++ b/src/systemd/src/libsystemd-network/lldp-network.c
@@ -1,9 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Tom Gundersen
- Copyright (C) 2014 Susant Sahani
+ Copyright © 2014 Tom Gundersen
+ Copyright © 2014 Susant Sahani
***/
#include "nm-sd-adapt.h"
diff --git a/src/systemd/src/libsystemd-network/lldp-network.h b/src/systemd/src/libsystemd-network/lldp-network.h
index 7a1e8b101a..1d773acc2d 100644
--- a/src/systemd/src/libsystemd-network/lldp-network.h
+++ b/src/systemd/src/libsystemd-network/lldp-network.h
@@ -2,10 +2,8 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Tom Gundersen
- Copyright (C) 2014 Susant Sahani
+ Copyright © 2014 Tom Gundersen
+ Copyright © 2014 Susant Sahani
***/
#include "sd-event.h"
diff --git a/src/systemd/src/libsystemd-network/network-internal.c b/src/systemd/src/libsystemd-network/network-internal.c
index e05f52d454..308762ee75 100644
--- a/src/systemd/src/libsystemd-network/network-internal.c
+++ b/src/systemd/src/libsystemd-network/network-internal.c
@@ -1,8 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
+ Copyright © 2013 Tom Gundersen <teg@jklm.no>
***/
#include "nm-sd-adapt.h"
diff --git a/src/systemd/src/libsystemd-network/network-internal.h b/src/systemd/src/libsystemd-network/network-internal.h
index d0076f453d..ef69e70155 100644
--- a/src/systemd/src/libsystemd-network/network-internal.h
+++ b/src/systemd/src/libsystemd-network/network-internal.h
@@ -2,9 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
+ Copyright © 2013 Tom Gundersen <teg@jklm.no>
***/
#include <stdbool.h>
@@ -12,6 +10,7 @@
#include "sd-dhcp-lease.h"
#include "condition.h"
+#include "conf-parser.h"
#include "set.h"
#include "udev.h"
@@ -35,33 +34,15 @@ bool net_match_config(Set *match_mac,
const char *dev_type,
const char *dev_name);
-int config_parse_net_condition(const char *unit, const char *filename, unsigned line,
- const char *section, unsigned section_line, const char *lvalue,
- int ltype, const char *rvalue, void *data, void *userdata);
-
-int config_parse_hwaddr(const char *unit, const char *filename, unsigned line,
- const char *section, unsigned section_line, const char *lvalue,
- int ltype, const char *rvalue, void *data, void *userdata);
-
-int config_parse_hwaddrs(const char *unit, const char *filename, unsigned line,
- const char *section, unsigned section_line, const char *lvalue,
- int ltype, const char *rvalue, void *data, void *userdata);
-
-int config_parse_ifnames(const char *unit, const char *filename, unsigned line,
- const char *section, unsigned section_line, const char *lvalue,
- int ltype, const char *rvalue, void *data, void *userdata);
-
-int config_parse_ifalias(const char *unit, const char *filename, unsigned line,
- const char *section, unsigned section_line, const char *lvalue,
- int ltype, const char *rvalue, void *data, void *userdata);
-
-int config_parse_iaid(const char *unit, const char *filename, unsigned line,
- const char *section, unsigned section_line, const char *lvalue,
- int ltype, const char *rvalue, void *data, void *userdata);
-
-int config_parse_bridge_port_priority(const char *unit, const char *filename, unsigned line,
- const char *section, unsigned section_line, const char *lvalue,
- int ltype, const char *rvalue, void *data, void *userdata);
+#if 0 /* NM_IGNORED */
+CONFIG_PARSER_PROTOTYPE(config_parse_net_condition);
+CONFIG_PARSER_PROTOTYPE(config_parse_hwaddr);
+CONFIG_PARSER_PROTOTYPE(config_parse_hwaddrs);
+CONFIG_PARSER_PROTOTYPE(config_parse_ifnames);
+CONFIG_PARSER_PROTOTYPE(config_parse_ifalias);
+CONFIG_PARSER_PROTOTYPE(config_parse_iaid);
+CONFIG_PARSER_PROTOTYPE(config_parse_bridge_port_priority);
+#endif /* NM_IGNORED */
int net_get_unique_predictable_data(struct udev_device *device, uint64_t *result);
const char *net_get_name(struct udev_device *device);
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-client.c b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
index ef2620f437..c2f81e1c40 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
@@ -1,8 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
+ Copyright © 2013 Intel Corporation. All rights reserved.
***/
#include "nm-sd-adapt.h"
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
index d92c512604..33a0796a83 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
@@ -1,9 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
- Copyright (C) 2014 Tom Gundersen
+ Copyright © 2013 Intel Corporation. All rights reserved.
+ Copyright © 2014 Tom Gundersen
***/
#include "nm-sd-adapt.h"
@@ -1036,7 +1034,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
if (r < 0)
return r;
- r = parse_env_file(lease_file, NEWLINE,
+ r = parse_env_file(NULL, lease_file, NEWLINE,
"ADDRESS", &address,
"ROUTER", &router,
"NETMASK", &netmask,
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
index 1cec602281..ca03f580e7 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
@@ -1,8 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
+ Copyright © 2014-2015 Intel Corporation. All rights reserved.
***/
#include "nm-sd-adapt.h"
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c
index 3952cd99f0..1c8346d40f 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c
@@ -1,9 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Tom Gundersen
- Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
+ Copyright © 2014 Tom Gundersen
+ Copyright © 2014-2015 Intel Corporation. All rights reserved.
***/
#include "nm-sd-adapt.h"
diff --git a/src/systemd/src/libsystemd-network/sd-ipv4acd.c b/src/systemd/src/libsystemd-network/sd-ipv4acd.c
index ed98c0b628..3766c1f3ff 100644
--- a/src/systemd/src/libsystemd-network/sd-ipv4acd.c
+++ b/src/systemd/src/libsystemd-network/sd-ipv4acd.c
@@ -1,9 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Axis Communications AB. All rights reserved.
- Copyright (C) 2015 Tom Gundersen
+ Copyright © 2014 Axis Communications AB. All rights reserved.
+ Copyright © 2015 Tom Gundersen
***/
#include "nm-sd-adapt.h"
diff --git a/src/systemd/src/libsystemd-network/sd-ipv4ll.c b/src/systemd/src/libsystemd-network/sd-ipv4ll.c
index 001ebbd8b0..ca1e0bdb7c 100644
--- a/src/systemd/src/libsystemd-network/sd-ipv4ll.c
+++ b/src/systemd/src/libsystemd-network/sd-ipv4ll.c
@@ -1,9 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Axis Communications AB. All rights reserved.
- Copyright (C) 2015 Tom Gundersen
+ Copyright © 2014 Axis Communications AB. All rights reserved.
+ Copyright © 2015 Tom Gundersen
***/
#include "nm-sd-adapt.h"
diff --git a/src/systemd/src/libsystemd-network/sd-lldp.c b/src/systemd/src/libsystemd-network/sd-lldp.c
index d88a0c6f2d..ea1dda4d17 100644
--- a/src/systemd/src/libsystemd-network/sd-lldp.c
+++ b/src/systemd/src/libsystemd-network/sd-lldp.c
@@ -1,9 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Tom Gundersen
- Copyright (C) 2014 Susant Sahani
+ Copyright © 2014 Tom Gundersen
+ Copyright © 2014 Susant Sahani
***/
#include "nm-sd-adapt.h"
diff --git a/src/systemd/src/libsystemd/sd-event/sd-event.c b/src/systemd/src/libsystemd/sd-event/sd-event.c
index 8a9b805501..f4d5dbe4b3 100644
--- a/src/systemd/src/libsystemd/sd-event/sd-event.c
+++ b/src/systemd/src/libsystemd/sd-event/sd-event.c
@@ -1,8 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
***/
#include "nm-sd-adapt.h"
@@ -17,6 +14,7 @@
#include "alloc-util.h"
#include "fd-util.h"
+#include "fs-util.h"
#include "hashmap.h"
#include "list.h"
#include "macro.h"
@@ -45,6 +43,7 @@ typedef enum EventSourceType {
SOURCE_POST,
SOURCE_EXIT,
SOURCE_WATCHDOG,
+ SOURCE_INOTIFY,
_SOURCE_EVENT_SOURCE_TYPE_MAX,
_SOURCE_EVENT_SOURCE_TYPE_INVALID = -1
} EventSourceType;
@@ -62,6 +61,7 @@ static const char* const event_source_type_table[_SOURCE_EVENT_SOURCE_TYPE_MAX]
[SOURCE_POST] = "post",
[SOURCE_EXIT] = "exit",
[SOURCE_WATCHDOG] = "watchdog",
+ [SOURCE_INOTIFY] = "inotify",
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(event_source_type, int);
@@ -73,12 +73,15 @@ typedef enum WakeupType {
WAKEUP_EVENT_SOURCE,
WAKEUP_CLOCK_DATA,
WAKEUP_SIGNAL_DATA,
+ WAKEUP_INOTIFY_DATA,
_WAKEUP_TYPE_MAX,
_WAKEUP_TYPE_INVALID = -1,
} WakeupType;
#define EVENT_SOURCE_IS_TIME(t) IN_SET((t), SOURCE_TIME_REALTIME, SOURCE_TIME_BOOTTIME, SOURCE_TIME_MONOTONIC, SOURCE_TIME_REALTIME_ALARM, SOURCE_TIME_BOOTTIME_ALARM)
+struct inode_data;
+
struct sd_event_source {
WakeupType wakeup;
@@ -102,6 +105,8 @@ struct sd_event_source {
uint64_t pending_iteration;
uint64_t prepare_iteration;
+ sd_event_destroy_t destroy_callback;
+
LIST_FIELDS(sd_event_source, sources);
union {
@@ -140,6 +145,12 @@ struct sd_event_source {
sd_event_handler_t callback;
unsigned prioq_index;
} exit;
+ struct {
+ sd_event_inotify_handler_t callback;
+ uint32_t mask;
+ struct inode_data *inode_data;
+ LIST_FIELDS(sd_event_source, by_inode_data);
+ } inotify;
};
};
@@ -174,6 +185,64 @@ struct signal_data {
sd_event_source *current;
};
+/* A structure listing all event sources currently watching a specific inode */
+struct inode_data {
+ /* The identifier for the inode, the combination of the .st_dev + .st_ino fields of the file */
+ ino_t ino;
+ dev_t dev;
+
+ /* An fd of the inode to watch. The fd is kept open until the next iteration of the loop, so that we can
+ * rearrange the priority still until then, as we need the original inode to change the priority as we need to
+ * add a watch descriptor to the right inotify for the priority which we can only do if we have a handle to the
+ * original inode. We keep a list of all inode_data objects with an open fd in the to_close list (see below) of
+ * the sd-event object, so that it is efficient to close everything, before entering the next event loop
+ * iteration. */
+ int fd;
+
+ /* The inotify "watch descriptor" */
+ int wd;
+
+ /* The combination of the mask of all inotify watches on this inode we manage. This is also the mask that has
+ * most recently been set on the watch descriptor. */
+ uint32_t combined_mask;
+
+ /* All event sources subscribed to this inode */
+ LIST_HEAD(sd_event_source, event_sources);
+
+ /* The inotify object we watch this inode with */
+ struct inotify_data *inotify_data;
+
+ /* A linked list of all inode data objects with fds to close (see above) */
+ LIST_FIELDS(struct inode_data, to_close);
+};
+
+/* A structure encapsulating an inotify fd */
+struct inotify_data {
+ WakeupType wakeup;
+
+ /* For each priority we maintain one inotify fd, so that we only have to dequeue a single event per priority at
+ * a time */
+
+ int fd;
+ int64_t priority;
+
+ Hashmap *inodes; /* The inode_data structures keyed by dev+ino */
+ Hashmap *wd; /* The inode_data structures keyed by the watch descriptor for each */
+
+ /* The buffer we read inotify events into */
+ union inotify_event_buffer buffer;
+ size_t buffer_filled; /* fill level of the buffer */
+
+ /* How many event sources are currently marked pending for this inotify. We won't read new events off the
+ * inotify fd as long as there are still pending events on the inotify (because we have no strategy of queuing
+ * the events locally if they can't be coalesced). */
+ unsigned n_pending;
+
+ /* A linked list of all inotify objects with data already read, that still need processing. We keep this list
+ * to make it efficient to figure out what inotify objects to process data on next. */
+ LIST_FIELDS(struct inotify_data, buffered);
+};
+
struct sd_event {
unsigned n_ref;
@@ -204,6 +273,14 @@ struct sd_event {
Prioq *exit;
+ Hashmap *inotify_data; /* indexed by priority */
+
+ /* A list of inode structures that still have an fd open, that we need to close before the next loop iteration */
+ LIST_HEAD(struct inode_data, inode_data_to_close);
+
+ /* A list of inotify objects that already have events buffered which aren't processed yet */
+ LIST_HEAD(struct inotify_data, inotify_data_buffered);
+
pid_t original_pid;
uint64_t iteration;
@@ -233,6 +310,7 @@ struct sd_event {
static thread_local sd_event *default_event = NULL;
static void source_disconnect(sd_event_source *s);
+static void event_gc_inode_data(sd_event *e, struct inode_data *d);
static sd_event *event_resolve(sd_event *e) {
return e == SD_EVENT_DEFAULT ? default_event : e;
@@ -414,6 +492,8 @@ static void event_free(sd_event *e) {
free(e->signal_sources);
hashmap_free(e->signal_data);
+ hashmap_free(e->inotify_data);
+
hashmap_free(e->child_sources);
set_free(e->post_sources);
free(e);
@@ -425,16 +505,32 @@ _public_ int sd_event_new(sd_event** ret) {
assert_return(ret, -EINVAL);
- e = new0(sd_event, 1);
+ e = new(sd_event, 1);
if (!e)
return -ENOMEM;
- e->n_ref = 1;
- e->watchdog_fd = e->epoll_fd = e->realtime.fd = e->boottime.fd = e->monotonic.fd = e->realtime_alarm.fd = e->boottime_alarm.fd = -1;
- e->realtime.next = e->boottime.next = e->monotonic.next = e->realtime_alarm.next = e->boottime_alarm.next = USEC_INFINITY;
- e->realtime.wakeup = e->boottime.wakeup = e->monotonic.wakeup = e->realtime_alarm.wakeup = e->boottime_alarm.wakeup = WAKEUP_CLOCK_DATA;
- e->original_pid = getpid_cached();
- e->perturb = USEC_INFINITY;
+ *e = (sd_event) {
+ .n_ref = 1,
+ .epoll_fd = -1,
+ .watchdog_fd = -1,
+ .realtime.wakeup = WAKEUP_CLOCK_DATA,
+ .realtime.fd = -1,
+ .realtime.next = USEC_INFINITY,
+ .boottime.wakeup = WAKEUP_CLOCK_DATA,
+ .boottime.fd = -1,
+ .boottime.next = USEC_INFINITY,
+ .monotonic.wakeup = WAKEUP_CLOCK_DATA,
+ .monotonic.fd = -1,
+ .monotonic.next = USEC_INFINITY,
+ .realtime_alarm.wakeup = WAKEUP_CLOCK_DATA,
+ .realtime_alarm.fd = -1,
+ .realtime_alarm.next = USEC_INFINITY,
+ .boottime_alarm.wakeup = WAKEUP_CLOCK_DATA,
+ .boottime_alarm.fd = -1,
+ .boottime_alarm.next = USEC_INFINITY,
+ .perturb = USEC_INFINITY,
+ .original_pid = getpid_cached(),
+ };
r = prioq_ensure_allocated(&e->pending, pending_prioq_compare);
if (r < 0)
@@ -520,18 +616,17 @@ static int source_io_register(
int enabled,
uint32_t events) {
- struct epoll_event ev = {};
+ struct epoll_event ev;
int r;
assert(s);
assert(s->type == SOURCE_IO);
assert(enabled != SD_EVENT_OFF);
- ev.events = events;
- ev.data.ptr = s;
-
- if (enabled == SD_EVENT_ONESHOT)
- ev.events |= EPOLLONESHOT;
+ ev = (struct epoll_event) {
+ .events = events | (enabled == SD_EVENT_ONESHOT ? EPOLLONESHOT : 0),
+ .data.ptr = s,
+ };
if (s->io.registered)
r = epoll_ctl(s->event->epoll_fd, EPOLL_CTL_MOD, s->io.fd, &ev);
@@ -623,7 +718,7 @@ static int event_make_signal_data(
int sig,
struct signal_data **ret) {
- struct epoll_event ev = {};
+ struct epoll_event ev;
struct signal_data *d;
bool added = false;
sigset_t ss_copy;
@@ -638,7 +733,7 @@ static int event_make_signal_data(
if (e->signal_sources && e->signal_sources[sig])
priority = e->signal_sources[sig]->priority;
else
- priority = 0;
+ priority = SD_EVENT_PRIORITY_NORMAL;
d = hashmap_get(e->signal_data, &priority);
if (d) {
@@ -652,13 +747,15 @@ static int event_make_signal_data(
if (r < 0)
return r;
- d = new0(struct signal_data, 1);
+ d = new(struct signal_data, 1);
if (!d)
return -ENOMEM;
- d->wakeup = WAKEUP_SIGNAL_DATA;
- d->fd = -1;
- d->priority = priority;
+ *d = (struct signal_data) {
+ .wakeup = WAKEUP_SIGNAL_DATA,
+ .fd = -1,
+ .priority = priority,
+ };
r = hashmap_put(e->signal_data, &d->priority, d);
if (r < 0) {
@@ -688,8 +785,10 @@ static int event_make_signal_data(
d->fd = fd_move_above_stdio(r);
- ev.events = EPOLLIN;
- ev.data.ptr = d;
+ ev = (struct epoll_event) {
+ .events = EPOLLIN,
+ .data.ptr = d,
+ };
r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, d->fd, &ev);
if (r < 0) {
@@ -856,6 +955,41 @@ static void source_disconnect(sd_event_source *s) {
prioq_remove(s->event->exit, s, &s->exit.prioq_index);
break;
+ case SOURCE_INOTIFY: {
+ struct inode_data *inode_data;
+
+ inode_data = s->inotify.inode_data;
+ if (inode_data) {
+ struct inotify_data *inotify_data;
+ assert_se(inotify_data = inode_data->inotify_data);
+
+ /* Detach this event source from the inode object */
+ LIST_REMOVE(inotify.by_inode_data, inode_data->event_sources, s);
+ s->inotify.inode_data = NULL;
+
+ if (s->pending) {
+ assert(inotify_data->n_pending > 0);
+ inotify_data->n_pending--;
+ }
+
+ /* Note that we don't reduce the inotify mask for the watch descriptor here if the inode is
+ * continued to being watched. That's because inotify doesn't really have an API for that: we
+ * can only change watch masks with access to the original inode either by fd or by path. But
+ * paths aren't stable, and keeping an O_PATH fd open all the time would mean wasting an fd
+ * continously and keeping the mount busy which we can't really do. We could reconstruct the
+ * original inode from /proc/self/fdinfo/$INOTIFY_FD (as all watch descriptors are listed
+ * there), but given the need for open_by_handle_at() which is privileged and not universally
+ * available this would be quite an incomplete solution. Hence we go the other way, leave the
+ * mask set, even if it is not minimized now, and ignore all events we aren't interested in
+ * anymore after reception. Yes, this sucks, but … Linux … */
+
+ /* Maybe release the inode data (and its inotify) */
+ event_gc_inode_data(s->event, inode_data);
+ }
+
+ break;
+ }
+
default:
assert_not_reached("Wut? I shouldn't exist.");
}
@@ -883,7 +1017,10 @@ static void source_free(sd_event_source *s) {
source_disconnect(s);
if (s->type == SOURCE_IO && s->io.owned)
- safe_close(s->io.fd);
+ s->io.fd = safe_close(s->io.fd);
+
+ if (s->destroy_callback)
+ s->destroy_callback(s->userdata);
free(s->description);
free(s);
@@ -930,6 +1067,19 @@ static int source_set_pending(sd_event_source *s, bool b) {
d->current = NULL;
}
+ if (s->type == SOURCE_INOTIFY) {
+
+ assert(s->inotify.inode_data);
+ assert(s->inotify.inode_data->inotify_data);
+
+ if (b)
+ s->inotify.inode_data->inotify_data->n_pending ++;
+ else {
+ assert(s->inotify.inode_data->inotify_data->n_pending > 0);
+ s->inotify.inode_data->inotify_data->n_pending --;
+ }
+ }
+
return 0;
}
@@ -938,15 +1088,18 @@ static sd_event_source *source_new(sd_event *e, bool floating, EventSourceType t
assert(e);
- s = new0(sd_event_source, 1);
+ s = new(sd_event_source, 1);
if (!s)
return NULL;
- s->n_ref = 1;
- s->event = e;
- s->floating = floating;
- s->type = type;
- s->pending_index = s->prepare_index = PRIOQ_IDX_NULL;
+ *s = (struct sd_event_source) {
+ .n_ref = 1,
+ .event = e,
+ .floating = floating,
+ .type = type,
+ .pending_index = PRIOQ_IDX_NULL,
+ .prepare_index = PRIOQ_IDX_NULL,
+ };
if (!floating)
sd_event_ref(e);
@@ -1023,7 +1176,7 @@ static int event_setup_timer_fd(
struct clock_data *d,
clockid_t clock) {
- struct epoll_event ev = {};
+ struct epoll_event ev;
int r, fd;
assert(e);
@@ -1038,8 +1191,10 @@ static int event_setup_timer_fd(
fd = fd_move_above_stdio(fd);
- ev.events = EPOLLIN;
- ev.data.ptr = d;
+ ev = (struct epoll_event) {
+ .events = EPOLLIN,
+ .data.ptr = d,
+ };
r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, fd, &ev);
if (r < 0) {
@@ -1378,6 +1533,405 @@ _public_ int sd_event_add_exit(
return 0;
}
+static void event_free_inotify_data(sd_event *e, struct inotify_data *d) {
+ assert(e);
+
+ if (!d)
+ return;
+
+ assert(hashmap_isempty(d->inodes));
+ assert(hashmap_isempty(d->wd));
+
+ if (d->buffer_filled > 0)
+ LIST_REMOVE(buffered, e->inotify_data_buffered, d);
+
+ hashmap_free(d->inodes);
+ hashmap_free(d->wd);
+
+ assert_se(hashmap_remove(e->inotify_data, &d->priority) == d);
+
+ if (d->fd >= 0) {
+ if (epoll_ctl(e->epoll_fd, EPOLL_CTL_DEL, d->fd, NULL) < 0)
+ log_debug_errno(errno, "Failed to remove inotify fd from epoll, ignoring: %m");
+
+ safe_close(d->fd);
+ }
+ free(d);
+}
+
+static int event_make_inotify_data(
+ sd_event *e,
+ int64_t priority,
+ struct inotify_data **ret) {
+
+ _cleanup_close_ int fd = -1;
+ struct inotify_data *d;
+ struct epoll_event ev;
+ int r;
+
+ assert(e);
+
+ d = hashmap_get(e->inotify_data, &priority);
+ if (d) {
+ if (ret)
+ *ret = d;
+ return 0;
+ }
+
+ fd = inotify_init1(IN_NONBLOCK|O_CLOEXEC);
+ if (fd < 0)
+ return -errno;
+
+ fd = fd_move_above_stdio(fd);
+
+ r = hashmap_ensure_allocated(&e->inotify_data, &uint64_hash_ops);
+ if (r < 0)
+ return r;
+
+ d = new(struct inotify_data, 1);
+ if (!d)
+ return -ENOMEM;
+
+ *d = (struct inotify_data) {
+ .wakeup = WAKEUP_INOTIFY_DATA,
+ .fd = TAKE_FD(fd),
+ .priority = priority,
+ };
+
+ r = hashmap_put(e->inotify_data, &d->priority, d);
+ if (r < 0) {
+ d->fd = safe_close(d->fd);
+ free(d);
+ return r;
+ }
+
+ ev = (struct epoll_event) {
+ .events = EPOLLIN,
+ .data.ptr = d,
+ };
+
+ if (epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, d->fd, &ev) < 0) {
+ r = -errno;
+ d->fd = safe_close(d->fd); /* let's close this ourselves, as event_free_inotify_data() would otherwise
+ * remove the fd from the epoll first, which we don't want as we couldn't
+ * add it in the first place. */
+ event_free_inotify_data(e, d);
+ return r;
+ }
+
+ if (ret)
+ *ret = d;
+
+ return 1;
+}
+
+static int inode_data_compare(const void *a, const void *b) {
+ const struct inode_data *x = a, *y = b;
+
+ 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;
+
+ return 0;
+}
+
+static void inode_data_hash_func(const void *p, struct siphash *state) {
+ const struct inode_data *d = p;
+
+ assert(p);
+
+ siphash24_compress(&d->dev, sizeof(d->dev), state);
+ siphash24_compress(&d->ino, sizeof(d->ino), state);
+}
+
+const struct hash_ops inode_data_hash_ops = {
+ .hash = inode_data_hash_func,
+ .compare = inode_data_compare
+};
+
+static void event_free_inode_data(
+ sd_event *e,
+ struct inode_data *d) {
+
+ assert(e);
+
+ if (!d)
+ return;
+
+ assert(!d->event_sources);
+
+ if (d->fd >= 0) {
+ LIST_REMOVE(to_close, e->inode_data_to_close, d);
+ safe_close(d->fd);
+ }
+
+ if (d->inotify_data) {
+
+ if (d->wd >= 0) {
+ if (d->inotify_data->fd >= 0) {
+ /* So here's a problem. At the time this runs the watch descriptor might already be
+ * invalidated, because an IN_IGNORED event might be queued right the moment we enter
+ * the syscall. Hence, whenever we get EINVAL, ignore it entirely, since it's a very
+ * likely case to happen. */
+
+ if (inotify_rm_watch(d->inotify_data->fd, d->wd) < 0 && errno != EINVAL)
+ log_debug_errno(errno, "Failed to remove watch descriptor %i from inotify, ignoring: %m", d->wd);
+ }
+
+ assert_se(hashmap_remove(d->inotify_data->wd, INT_TO_PTR(d->wd)) == d);
+ }
+
+ assert_se(hashmap_remove(d->inotify_data->inodes, d) == d);
+ }
+
+ free(d);
+}
+
+static void event_gc_inode_data(
+ sd_event *e,
+ struct inode_data *d) {
+
+ struct inotify_data *inotify_data;
+
+ assert(e);
+
+ if (!d)
+ return;
+
+ if (d->event_sources)
+ return;
+
+ inotify_data = d->inotify_data;
+ event_free_inode_data(e, d);
+
+ if (inotify_data && hashmap_isempty(inotify_data->inodes))
+ event_free_inotify_data(e, inotify_data);
+}
+
+static int event_make_inode_data(
+ sd_event *e,
+ struct inotify_data *inotify_data,
+ dev_t dev,
+ ino_t ino,
+ struct inode_data **ret) {
+
+ struct inode_data *d, key;
+ int r;
+
+ assert(e);
+ assert(inotify_data);
+
+ key = (struct inode_data) {
+ .ino = ino,
+ .dev = dev,
+ };
+
+ d = hashmap_get(inotify_data->inodes, &key);
+ if (d) {
+ if (ret)
+ *ret = d;
+
+ return 0;
+ }
+
+ r = hashmap_ensure_allocated(&inotify_data->inodes, &inode_data_hash_ops);
+ if (r < 0)
+ return r;
+
+ d = new(struct inode_data, 1);
+ if (!d)
+ return -ENOMEM;
+
+ *d = (struct inode_data) {
+ .dev = dev,
+ .ino = ino,
+ .wd = -1,
+ .fd = -1,
+ .inotify_data = inotify_data,
+ };
+
+ r = hashmap_put(inotify_data->inodes, d, d);
+ if (r < 0) {
+ free(d);
+ return r;
+ }
+
+ if (ret)
+ *ret = d;
+
+ return 1;
+}
+
+static uint32_t inode_data_determine_mask(struct inode_data *d) {
+ bool excl_unlink = true;
+ uint32_t combined = 0;
+ sd_event_source *s;
+
+ assert(d);
+
+ /* Combines the watch masks of all event sources watching this inode. We generally just OR them together, but
+ * the IN_EXCL_UNLINK flag is ANDed instead.
+ *
+ * Note that we add all sources to the mask here, regardless whether enabled, disabled or oneshot. That's
+ * because we cannot change the mask anymore after the event source was created once, since the kernel has no
+ * API for that. Hence we need to subscribe to the maximum mask we ever might be interested in, and supress
+ * events we don't care for client-side. */
+
+ LIST_FOREACH(inotify.by_inode_data, s, d->event_sources) {
+
+ if ((s->inotify.mask & IN_EXCL_UNLINK) == 0)
+ excl_unlink = false;
+
+ combined |= s->inotify.mask;
+ }
+
+ return (combined & ~(IN_ONESHOT|IN_DONT_FOLLOW|IN_ONLYDIR|IN_EXCL_UNLINK)) | (excl_unlink ? IN_EXCL_UNLINK : 0);
+}
+
+static int inode_data_realize_watch(sd_event *e, struct inode_data *d) {
+ uint32_t combined_mask;
+ int wd, r;
+
+ assert(d);
+ assert(d->fd >= 0);
+
+ combined_mask = inode_data_determine_mask(d);
+
+ if (d->wd >= 0 && combined_mask == d->combined_mask)
+ return 0;
+
+ r = hashmap_ensure_allocated(&d->inotify_data->wd, NULL);
+ if (r < 0)
+ return r;
+
+ wd = inotify_add_watch_fd(d->inotify_data->fd, d->fd, combined_mask);
+ if (wd < 0)
+ return -errno;
+
+ if (d->wd < 0) {
+ r = hashmap_put(d->inotify_data->wd, INT_TO_PTR(wd), d);
+ if (r < 0) {
+ (void) inotify_rm_watch(d->inotify_data->fd, wd);
+ return r;
+ }
+
+ d->wd = wd;
+
+ } else if (d->wd != wd) {
+
+ log_debug("Weird, the watch descriptor we already knew for this inode changed?");
+ (void) inotify_rm_watch(d->fd, wd);
+ return -EINVAL;
+ }
+
+ d->combined_mask = combined_mask;
+ return 1;
+}
+
+_public_ int sd_event_add_inotify(
+ sd_event *e,
+ sd_event_source **ret,
+ const char *path,
+ uint32_t mask,
+ sd_event_inotify_handler_t callback,
+ void *userdata) {
+
+ bool rm_inotify = false, rm_inode = false;
+ struct inotify_data *inotify_data = NULL;
+ struct inode_data *inode_data = NULL;
+ _cleanup_close_ int fd = -1;
+ sd_event_source *s;
+ struct stat st;
+ int r;
+
+ assert_return(e, -EINVAL);
+ assert_return(e = event_resolve(e), -ENOPKG);
+ assert_return(path, -EINVAL);
+ assert_return(callback, -EINVAL);
+ assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
+ assert_return(!event_pid_changed(e), -ECHILD);
+
+ /* Refuse IN_MASK_ADD since we coalesce watches on the same inode, and hence really don't want to merge
+ * masks. Or in other words, this whole code exists only to manage IN_MASK_ADD type operations for you, hence
+ * the user can't use them for us. */
+ if (mask & IN_MASK_ADD)
+ return -EINVAL;
+
+ fd = open(path, O_PATH|O_CLOEXEC|
+ (mask & IN_ONLYDIR ? O_DIRECTORY : 0)|
+ (mask & IN_DONT_FOLLOW ? O_NOFOLLOW : 0));
+ if (fd < 0)
+ return -errno;
+
+ if (fstat(fd, &st) < 0)
+ return -errno;
+
+ s = source_new(e, !ret, SOURCE_INOTIFY);
+ if (!s)
+ return -ENOMEM;
+
+ s->enabled = mask & IN_ONESHOT ? SD_EVENT_ONESHOT : SD_EVENT_ON;
+ s->inotify.mask = mask;
+ s->inotify.callback = callback;
+ s->userdata = userdata;
+
+ /* Allocate an inotify object for this priority, and an inode object within it */
+ r = event_make_inotify_data(e, SD_EVENT_PRIORITY_NORMAL, &inotify_data);
+ if (r < 0)
+ goto fail;
+ rm_inotify = r > 0;
+
+ r = event_make_inode_data(e, inotify_data, st.st_dev, st.st_ino, &inode_data);
+ if (r < 0)
+ goto fail;
+ rm_inode = r > 0;
+
+ /* Keep the O_PATH fd around until the first iteration of the loop, so that we can still change the priority of
+ * the event source, until then, for which we need the original inode. */
+ if (inode_data->fd < 0) {
+ inode_data->fd = TAKE_FD(fd);
+ LIST_PREPEND(to_close, e->inode_data_to_close, inode_data);
+ }
+
+ /* Link our event source to the inode data object */
+ LIST_PREPEND(inotify.by_inode_data, inode_data->event_sources, s);
+ s->inotify.inode_data = inode_data;
+
+ rm_inode = rm_inotify = false;
+
+ /* Actually realize the watch now */
+ r = inode_data_realize_watch(e, inode_data);
+ if (r < 0)
+ goto fail;
+
+ (void) sd_event_source_set_description(s, path);
+
+ if (ret)
+ *ret = s;
+
+ return 0;
+
+fail:
+ source_free(s);
+
+ if (rm_inode)
+ event_free_inode_data(e, inode_data);
+
+ if (rm_inotify)
+ event_free_inotify_data(e, inotify_data);
+
+ return r;
+}
+
_public_ sd_event_source* sd_event_source_ref(sd_event_source *s) {
if (!s)
@@ -1532,6 +2086,10 @@ _public_ int sd_event_source_set_io_events(sd_event_source *s, uint32_t events)
if (s->io.events == events && !(events & EPOLLET))
return 0;
+ r = source_set_pending(s, false);
+ if (r < 0)
+ return r;
+
if (s->enabled != SD_EVENT_OFF) {
r = source_io_register(s, s->enabled, events);
if (r < 0)
@@ -1539,7 +2097,6 @@ _public_ int sd_event_source_set_io_events(sd_event_source *s, uint32_t events)
}
s->io.events = events;
- source_set_pending(s, false);
return 0;
}
@@ -1572,6 +2129,9 @@ _public_ int sd_event_source_get_priority(sd_event_source *s, int64_t *priority)
}
_public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority) {
+ bool rm_inotify = false, rm_inode = false;
+ struct inotify_data *new_inotify_data = NULL;
+ struct inode_data *new_inode_data = NULL;
int r;
assert_return(s, -EINVAL);
@@ -1581,7 +2141,59 @@ _public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority)
if (s->priority == priority)
return 0;
- if (s->type == SOURCE_SIGNAL && s->enabled != SD_EVENT_OFF) {
+ if (s->type == SOURCE_INOTIFY) {
+ struct inode_data *old_inode_data;
+
+ assert(s->inotify.inode_data);
+ old_inode_data = s->inotify.inode_data;
+
+ /* We need the original fd to change the priority. If we don't have it we can't change the priority,
+ * anymore. Note that we close any fds when entering the next event loop iteration, i.e. for inotify
+ * events we allow priority changes only until the first following iteration. */
+ if (old_inode_data->fd < 0)
+ return -EOPNOTSUPP;
+
+ r = event_make_inotify_data(s->event, priority, &new_inotify_data);
+ if (r < 0)
+ return r;
+ rm_inotify = r > 0;
+
+ r = event_make_inode_data(s->event, new_inotify_data, old_inode_data->dev, old_inode_data->ino, &new_inode_data);
+ if (r < 0)
+ goto fail;
+ rm_inode = r > 0;
+
+ if (new_inode_data->fd < 0) {
+ /* Duplicate the fd for the new inode object if we don't have any yet */
+ new_inode_data->fd = fcntl(old_inode_data->fd, F_DUPFD_CLOEXEC, 3);
+ if (new_inode_data->fd < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ LIST_PREPEND(to_close, s->event->inode_data_to_close, new_inode_data);
+ }
+
+ /* Move the event source to the new inode data structure */
+ LIST_REMOVE(inotify.by_inode_data, old_inode_data->event_sources, s);
+ LIST_PREPEND(inotify.by_inode_data, new_inode_data->event_sources, s);
+ s->inotify.inode_data = new_inode_data;
+
+ /* Now create the new watch */
+ r = inode_data_realize_watch(s->event, new_inode_data);
+ if (r < 0) {
+ /* Move it back */
+ LIST_REMOVE(inotify.by_inode_data, new_inode_data->event_sources, s);
+ LIST_PREPEND(inotify.by_inode_data, old_inode_data->event_sources, s);
+ s->inotify.inode_data = old_inode_data;
+ goto fail;
+ }
+
+ s->priority = priority;
+
+ event_gc_inode_data(s->event, old_inode_data);
+
+ } else if (s->type == SOURCE_SIGNAL && s->enabled != SD_EVENT_OFF) {
struct signal_data *old, *d;
/* Move us from the signalfd belonging to the old
@@ -1611,6 +2223,15 @@ _public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority)
prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
return 0;
+
+fail:
+ if (rm_inode)
+ event_free_inode_data(s->event, new_inode_data);
+
+ if (rm_inotify)
+ event_free_inotify_data(s->event, new_inotify_data);
+
+ return r;
}
_public_ int sd_event_source_get_enabled(sd_event_source *s, int *m) {
@@ -1639,6 +2260,13 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
if (m == SD_EVENT_OFF) {
+ /* Unset the pending flag when this event source is disabled */
+ if (!IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) {
+ r = source_set_pending(s, false);
+ if (r < 0)
+ return r;
+ }
+
switch (s->type) {
case SOURCE_IO:
@@ -1685,6 +2313,7 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
case SOURCE_DEFER:
case SOURCE_POST:
+ case SOURCE_INOTIFY:
s->enabled = m;
break;
@@ -1693,6 +2322,14 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
}
} else {
+
+ /* Unset the pending flag when this event source is enabled */
+ if (s->enabled == SD_EVENT_OFF && !IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) {
+ r = source_set_pending(s, false);
+ if (r < 0)
+ return r;
+ }
+
switch (s->type) {
case SOURCE_IO:
@@ -1757,6 +2394,7 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
case SOURCE_DEFER:
case SOURCE_POST:
+ case SOURCE_INOTIFY:
s->enabled = m;
break;
@@ -1786,15 +2424,18 @@ _public_ int sd_event_source_get_time(sd_event_source *s, uint64_t *usec) {
_public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) {
struct clock_data *d;
+ int r;
assert_return(s, -EINVAL);
assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM);
assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(s->event), -ECHILD);
- s->time.next = usec;
+ r = source_set_pending(s, false);
+ if (r < 0)
+ return r;
- source_set_pending(s, false);
+ s->time.next = usec;
d = event_get_clock_data(s->event, s->type);
assert(d);
@@ -1818,6 +2459,7 @@ _public_ int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *use
_public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec) {
struct clock_data *d;
+ int r;
assert_return(s, -EINVAL);
assert_return(usec != (uint64_t) -1, -EINVAL);
@@ -1825,13 +2467,15 @@ _public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec
assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(s->event), -ECHILD);
+ r = source_set_pending(s, false);
+ if (r < 0)
+ return r;
+
if (usec == 0)
usec = DEFAULT_ACCURACY_USEC;
s->time.accuracy = usec;
- source_set_pending(s, false);
-
d = event_get_clock_data(s->event, s->type);
assert(d);
@@ -1861,6 +2505,16 @@ _public_ int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid) {
return 0;
}
+_public_ int sd_event_source_get_inotify_mask(sd_event_source *s, uint32_t *mask) {
+ assert_return(s, -EINVAL);
+ assert_return(mask, -EINVAL);
+ assert_return(s->type == SOURCE_INOTIFY, -EDOM);
+ assert_return(!event_pid_changed(s->event), -ECHILD);
+
+ *mask = s->inotify.mask;
+ return 0;
+}
+
_public_ int sd_event_source_set_prepare(sd_event_source *s, sd_event_handler_t callback) {
int r;
@@ -2194,6 +2848,7 @@ static int process_signal(sd_event *e, struct signal_data *d, uint32_t events) {
int r;
assert(e);
+ assert(d);
assert_return(events == EPOLLIN, -EIO);
/* If there's a signal queued on this priority and SIGCHLD is
@@ -2250,6 +2905,160 @@ static int process_signal(sd_event *e, struct signal_data *d, uint32_t events) {
}
}
+static int event_inotify_data_read(sd_event *e, struct inotify_data *d, uint32_t revents) {
+ ssize_t n;
+
+ assert(e);
+ assert(d);
+
+ assert_return(revents == EPOLLIN, -EIO);
+
+ /* If there's already an event source pending for this priority, don't read another */
+ if (d->n_pending > 0)
+ return 0;
+
+ /* Is the read buffer non-empty? If so, let's not read more */
+ if (d->buffer_filled > 0)
+ return 0;
+
+ n = read(d->fd, &d->buffer, sizeof(d->buffer));
+ if (n < 0) {
+ if (IN_SET(errno, EAGAIN, EINTR))
+ return 0;
+
+ return -errno;
+ }
+
+ assert(n > 0);
+ d->buffer_filled = (size_t) n;
+ LIST_PREPEND(buffered, e->inotify_data_buffered, d);
+
+ return 1;
+}
+
+static void event_inotify_data_drop(sd_event *e, struct inotify_data *d, size_t sz) {
+ assert(e);
+ assert(d);
+ assert(sz <= d->buffer_filled);
+
+ if (sz == 0)
+ return;
+
+ /* Move the rest to the buffer to the front, in order to get things properly aligned again */
+ memmove(d->buffer.raw, d->buffer.raw + sz, d->buffer_filled - sz);
+ d->buffer_filled -= sz;
+
+ if (d->buffer_filled == 0)
+ LIST_REMOVE(buffered, e->inotify_data_buffered, d);
+}
+
+static int event_inotify_data_process(sd_event *e, struct inotify_data *d) {
+ int r;
+
+ assert(e);
+ assert(d);
+
+ /* If there's already an event source pending for this priority, don't read another */
+ if (d->n_pending > 0)
+ return 0;
+
+ while (d->buffer_filled > 0) {
+ size_t sz;
+
+ /* Let's validate that the event structures are complete */
+ if (d->buffer_filled < offsetof(struct inotify_event, name))
+ return -EIO;
+
+ sz = offsetof(struct inotify_event, name) + d->buffer.ev.len;
+ if (d->buffer_filled < sz)
+ return -EIO;
+
+ if (d->buffer.ev.mask & IN_Q_OVERFLOW) {
+ struct inode_data *inode_data;
+ Iterator i;
+
+ /* The queue overran, let's pass this event to all event sources connected to this inotify
+ * object */
+
+ HASHMAP_FOREACH(inode_data, d->inodes, i) {
+ sd_event_source *s;
+
+ LIST_FOREACH(inotify.by_inode_data, s, inode_data->event_sources) {
+
+ if (s->enabled == SD_EVENT_OFF)
+ continue;
+
+ r = source_set_pending(s, true);
+ if (r < 0)
+ return r;
+ }
+ }
+ } else {
+ struct inode_data *inode_data;
+ sd_event_source *s;
+
+ /* Find the inode object for this watch descriptor. If IN_IGNORED is set we also remove it from
+ * our watch descriptor table. */
+ if (d->buffer.ev.mask & IN_IGNORED) {
+
+ inode_data = hashmap_remove(d->wd, INT_TO_PTR(d->buffer.ev.wd));
+ if (!inode_data) {
+ event_inotify_data_drop(e, d, sz);
+ continue;
+ }
+
+ /* The watch descriptor was removed by the kernel, let's drop it here too */
+ inode_data->wd = -1;
+ } else {
+ inode_data = hashmap_get(d->wd, INT_TO_PTR(d->buffer.ev.wd));
+ if (!inode_data) {
+ event_inotify_data_drop(e, d, sz);
+ continue;
+ }
+ }
+
+ /* Trigger all event sources that are interested in these events. Also trigger all event
+ * sources if IN_IGNORED or IN_UNMOUNT is set. */
+ LIST_FOREACH(inotify.by_inode_data, s, inode_data->event_sources) {
+
+ if (s->enabled == SD_EVENT_OFF)
+ continue;
+
+ if ((d->buffer.ev.mask & (IN_IGNORED|IN_UNMOUNT)) == 0 &&
+ (s->inotify.mask & d->buffer.ev.mask & IN_ALL_EVENTS) == 0)
+ continue;
+
+ r = source_set_pending(s, true);
+ if (r < 0)
+ return r;
+ }
+ }
+
+ /* Something pending now? If so, let's finish, otherwise let's read more. */
+ if (d->n_pending > 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+static int process_inotify(sd_event *e) {
+ struct inotify_data *d;
+ int r, done = 0;
+
+ assert(e);
+
+ LIST_FOREACH(buffered, d, e->inotify_data_buffered) {
+ r = event_inotify_data_process(e, d);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ done ++;
+ }
+
+ return done;
+}
+
static int source_dispatch(sd_event_source *s) {
EventSourceType saved_type;
int r = 0;
@@ -2319,7 +3128,7 @@ static int source_dispatch(sd_event_source *s) {
/* Now, reap the PID for good. */
if (zombie)
- waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG|WEXITED);
+ (void) waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG|WEXITED);
break;
}
@@ -2336,6 +3145,28 @@ static int source_dispatch(sd_event_source *s) {
r = s->exit.callback(s, s->userdata);
break;
+ case SOURCE_INOTIFY: {
+ struct sd_event *e = s->event;
+ struct inotify_data *d;
+ size_t sz;
+
+ assert(s->inotify.inode_data);
+ assert_se(d = s->inotify.inode_data->inotify_data);
+
+ assert(d->buffer_filled >= offsetof(struct inotify_event, name));
+ sz = offsetof(struct inotify_event, name) + d->buffer.ev.len;
+ assert(d->buffer_filled >= sz);
+
+ r = s->inotify.callback(s, &d->buffer.ev, s->userdata);
+
+ /* When no event is pending anymore on this inotify object, then let's drop the event from the
+ * buffer. */
+ if (d->n_pending == 0)
+ event_inotify_data_drop(e, d, sz);
+
+ break;
+ }
+
case SOURCE_WATCHDOG:
case _SOURCE_EVENT_SOURCE_TYPE_MAX:
case _SOURCE_EVENT_SOURCE_TYPE_INVALID:
@@ -2470,6 +3301,25 @@ static int process_watchdog(sd_event *e) {
return arm_watchdog(e);
}
+static void event_close_inode_data_fds(sd_event *e) {
+ struct inode_data *d;
+
+ assert(e);
+
+ /* Close the fds pointing to the inodes to watch now. We need to close them as they might otherwise pin
+ * filesystems. But we can't close them right-away as we need them as long as the user still wants to make
+ * adjustments to the even source, such as changing the priority (which requires us to remove and readd a watch
+ * for the inode). Hence, let's close them when entering the first iteration after they were added, as a
+ * compromise. */
+
+ while ((d = e->inode_data_to_close)) {
+ assert(d->fd >= 0);
+ d->fd = safe_close(d->fd);
+
+ LIST_REMOVE(to_close, e->inode_data_to_close, d);
+ }
+}
+
_public_ int sd_event_prepare(sd_event *e) {
int r;
@@ -2510,6 +3360,8 @@ _public_ int sd_event_prepare(sd_event *e) {
if (r < 0)
return r;
+ event_close_inode_data_fds(e);
+
if (event_next_pending(e) || e->need_process_child)
goto pending;
@@ -2545,6 +3397,10 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) {
ev_queue_max = MAX(e->n_sources, 1u);
ev_queue = newa(struct epoll_event, ev_queue_max);
+ /* If we still have inotify data buffered, then query the other fds, but don't wait on it */
+ if (e->inotify_data_buffered)
+ timeout = 0;
+
m = epoll_wait(e->epoll_fd, ev_queue, ev_queue_max,
timeout == (uint64_t) -1 ? -1 : (int) ((timeout + USEC_PER_MSEC - 1) / USEC_PER_MSEC));
if (m < 0) {
@@ -2582,6 +3438,10 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) {
r = process_signal(e, ev_queue[i].data.ptr, ev_queue[i].events);
break;
+ case WAKEUP_INOTIFY_DATA:
+ r = event_inotify_data_read(e, ev_queue[i].data.ptr, ev_queue[i].events);
+ break;
+
default:
assert_not_reached("Invalid wake-up pointer");
}
@@ -2620,6 +3480,10 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) {
goto finish;
}
+ r = process_inotify(e);
+ if (r < 0)
+ goto finish;
+
if (event_next_pending(e)) {
e->state = SD_EVENT_PENDING;
@@ -2858,7 +3722,7 @@ _public_ int sd_event_set_watchdog(sd_event *e, int b) {
return e->watchdog;
if (b) {
- struct epoll_event ev = {};
+ struct epoll_event ev;
r = sd_watchdog_enabled(false, &e->watchdog_period);
if (r <= 0)
@@ -2876,8 +3740,10 @@ _public_ int sd_event_set_watchdog(sd_event *e, int b) {
if (r < 0)
goto fail;
- ev.events = EPOLLIN;
- ev.data.ptr = INT_TO_PTR(SOURCE_WATCHDOG);
+ ev = (struct epoll_event) {
+ .events = EPOLLIN,
+ .data.ptr = INT_TO_PTR(SOURCE_WATCHDOG),
+ };
r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, e->watchdog_fd, &ev);
if (r < 0) {
@@ -2916,4 +3782,20 @@ _public_ int sd_event_get_iteration(sd_event *e, uint64_t *ret) {
*ret = e->iteration;
return 0;
}
+
+_public_ int sd_event_source_set_destroy_callback(sd_event_source *s, sd_event_destroy_t callback) {
+ assert_return(s, -EINVAL);
+
+ s->destroy_callback = callback;
+ return 0;
+}
+
+_public_ int sd_event_source_get_destroy_callback(sd_event_source *s, sd_event_destroy_t *ret) {
+ assert_return(s, -EINVAL);
+
+ if (ret)
+ *ret = s->destroy_callback;
+
+ return !!s->destroy_callback;
+}
#endif /* NM_IGNORED */
diff --git a/src/systemd/src/libsystemd/sd-id128/id128-util.c b/src/systemd/src/libsystemd/sd-id128/id128-util.c
index 26eef0fd6a..03a3869928 100644
--- a/src/systemd/src/libsystemd/sd-id128/id128-util.c
+++ b/src/systemd/src/libsystemd/sd-id128/id128-util.c
@@ -1,8 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
***/
#include "nm-sd-adapt.h"
diff --git a/src/systemd/src/libsystemd/sd-id128/id128-util.h b/src/systemd/src/libsystemd/sd-id128/id128-util.h
index 9aeb27a220..f0b4eca581 100644
--- a/src/systemd/src/libsystemd/sd-id128/id128-util.h
+++ b/src/systemd/src/libsystemd/sd-id128/id128-util.h
@@ -2,9 +2,6 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
***/
#include <stdbool.h>
diff --git a/src/systemd/src/libsystemd/sd-id128/sd-id128.c b/src/systemd/src/libsystemd/sd-id128/sd-id128.c
index de0ae600f2..8fe8ff4335 100644
--- a/src/systemd/src/libsystemd/sd-id128/sd-id128.c
+++ b/src/systemd/src/libsystemd/sd-id128/sd-id128.c
@@ -1,8 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
***/
#include "nm-sd-adapt.h"
@@ -102,7 +99,7 @@ _public_ int sd_id128_get_machine(sd_id128_t *ret) {
return r;
if (sd_id128_is_null(saved_machine_id))
- return -EINVAL;
+ return -ENOMEDIUM;
}
*ret = saved_machine_id;
diff --git a/src/systemd/src/shared/dns-domain.c b/src/systemd/src/shared/dns-domain.c
index 3f41be621e..ab03404324 100644
--- a/src/systemd/src/shared/dns-domain.c
+++ b/src/systemd/src/shared/dns-domain.c
@@ -1,8 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
***/
#include "nm-sd-adapt.h"
@@ -360,10 +357,7 @@ int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded,
if (encoded_size <= 0 || encoded_size > DNS_LABEL_MAX)
return -EINVAL;
- if (encoded_size < sizeof(IDNA_ACE_PREFIX)-1)
- return 0;
-
- if (memcmp(encoded, IDNA_ACE_PREFIX, sizeof(IDNA_ACE_PREFIX) -1) != 0)
+ if (!memory_startswith(encoded, encoded_size, IDNA_ACE_PREFIX))
return 0;
input = stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size);
diff --git a/src/systemd/src/shared/dns-domain.h b/src/systemd/src/shared/dns-domain.h
index 47bd535756..8781eec65d 100644
--- a/src/systemd/src/shared/dns-domain.h
+++ b/src/systemd/src/shared/dns-domain.h
@@ -2,9 +2,6 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
***/
#include <errno.h>
@@ -25,7 +22,7 @@
#define DNS_HOSTNAME_MAX 253
/* Maximum length of a full hostname, on the wire, including the final NUL byte */
-#define DNS_WIRE_FOMAT_HOSTNAME_MAX 255
+#define DNS_WIRE_FORMAT_HOSTNAME_MAX 255
/* Maximum number of labels per valid hostname */
#define DNS_N_LABELS_MAX 127
diff --git a/src/systemd/src/systemd/_sd-common.h b/src/systemd/src/systemd/_sd-common.h
index b4400e7b36..7b54d179eb 100644
--- a/src/systemd/src/systemd/_sd-common.h
+++ b/src/systemd/src/systemd/_sd-common.h
@@ -3,9 +3,6 @@
#define foosdcommonhfoo
/***
- This file is part of systemd.
-
- Copyright 2013 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
diff --git a/src/systemd/src/systemd/sd-dhcp-client.h b/src/systemd/src/systemd/sd-dhcp-client.h
index fd0a569362..931b0e890b 100644
--- a/src/systemd/src/systemd/sd-dhcp-client.h
+++ b/src/systemd/src/systemd/sd-dhcp-client.h
@@ -3,9 +3,7 @@
#define foosddhcpclienthfoo
/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
+ Copyright © 2013 Intel Corporation. All rights reserved.
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
diff --git a/src/systemd/src/systemd/sd-dhcp-lease.h b/src/systemd/src/systemd/sd-dhcp-lease.h
index 3cc7fcabe3..16c05661ec 100644
--- a/src/systemd/src/systemd/sd-dhcp-lease.h
+++ b/src/systemd/src/systemd/sd-dhcp-lease.h
@@ -3,10 +3,8 @@
#define foosddhcpleasehfoo
/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
- Copyright (C) 2014 Tom Gundersen
+ Copyright © 2013 Intel Corporation. All rights reserved.
+ Copyright © 2014 Tom Gundersen
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
diff --git a/src/systemd/src/systemd/sd-dhcp6-client.h b/src/systemd/src/systemd/sd-dhcp6-client.h
index cadb32a051..4f3b2d9e2e 100644
--- a/src/systemd/src/systemd/sd-dhcp6-client.h
+++ b/src/systemd/src/systemd/sd-dhcp6-client.h
@@ -3,9 +3,7 @@
#define foosddhcp6clienthfoo
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Intel Corporation. All rights reserved.
+ Copyright © 2014 Intel Corporation. All rights reserved.
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
diff --git a/src/systemd/src/systemd/sd-dhcp6-lease.h b/src/systemd/src/systemd/sd-dhcp6-lease.h
index 22a5f8ce75..a673de5edd 100644
--- a/src/systemd/src/systemd/sd-dhcp6-lease.h
+++ b/src/systemd/src/systemd/sd-dhcp6-lease.h
@@ -3,10 +3,8 @@
#define foosddhcp6leasehfoo
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Tom Gundersen
- Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
+ Copyright © 2014 Tom Gundersen
+ Copyright © 2014-2015 Intel Corporation. All rights reserved.
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
diff --git a/src/systemd/src/systemd/sd-event.h b/src/systemd/src/systemd/sd-event.h
index ec4b7bcf69..7fcae4ac49 100644
--- a/src/systemd/src/systemd/sd-event.h
+++ b/src/systemd/src/systemd/sd-event.h
@@ -3,9 +3,6 @@
#define foosdeventhfoo
/***
- This file is part of systemd.
-
- Copyright 2013 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
@@ -24,6 +21,7 @@
#include <inttypes.h>
#include <signal.h>
#include <sys/epoll.h>
+#include <sys/inotify.h>
#include <sys/signalfd.h>
#include <sys/types.h>
#include <time.h>
@@ -78,6 +76,8 @@ typedef int (*sd_event_child_handler_t)(sd_event_source *s, const siginfo_t *si,
#else
typedef void* sd_event_child_handler_t;
#endif
+typedef int (*sd_event_inotify_handler_t)(sd_event_source *s, const struct inotify_event *event, void *userdata);
+typedef void (*sd_event_destroy_t)(void *userdata);
int sd_event_default(sd_event **e);
@@ -89,6 +89,7 @@ int sd_event_add_io(sd_event *e, sd_event_source **s, int fd, uint32_t events, s
int sd_event_add_time(sd_event *e, sd_event_source **s, clockid_t clock, uint64_t usec, uint64_t accuracy, sd_event_time_handler_t callback, void *userdata);
int sd_event_add_signal(sd_event *e, sd_event_source **s, int sig, sd_event_signal_handler_t callback, void *userdata);
int sd_event_add_child(sd_event *e, sd_event_source **s, pid_t pid, int options, sd_event_child_handler_t callback, void *userdata);
+int sd_event_add_inotify(sd_event *e, sd_event_source **s, const char *path, uint32_t mask, sd_event_inotify_handler_t callback, void *userdata);
int sd_event_add_defer(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata);
int sd_event_add_post(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata);
int sd_event_add_exit(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata);
@@ -139,6 +140,9 @@ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec);
int sd_event_source_get_time_clock(sd_event_source *s, clockid_t *clock);
int sd_event_source_get_signal(sd_event_source *s);
int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid);
+int sd_event_source_get_inotify_mask(sd_event_source *s, uint32_t *ret);
+int sd_event_source_set_destroy_callback(sd_event_source *s, sd_event_destroy_t callback);
+int sd_event_source_get_destroy_callback(sd_event_source *s, sd_event_destroy_t *ret);
/* Define helpers so that __attribute__((cleanup(sd_event_unrefp))) and similar may be used. */
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event, sd_event_unref);
diff --git a/src/systemd/src/systemd/sd-id128.h b/src/systemd/src/systemd/sd-id128.h
index 67fc595669..b24fd06f01 100644
--- a/src/systemd/src/systemd/sd-id128.h
+++ b/src/systemd/src/systemd/sd-id128.h
@@ -3,9 +3,6 @@
#define foosdid128hfoo
/***
- This file is part of systemd.
-
- Copyright 2011 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
diff --git a/src/systemd/src/systemd/sd-ipv4acd.h b/src/systemd/src/systemd/sd-ipv4acd.h
index 677ae3b216..259db26330 100644
--- a/src/systemd/src/systemd/sd-ipv4acd.h
+++ b/src/systemd/src/systemd/sd-ipv4acd.h
@@ -3,10 +3,8 @@
#define foosdipv4acdfoo
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Axis Communications AB. All rights reserved.
- Copyright (C) 2015 Tom Gundersen
+ Copyright © 2014 Axis Communications AB. All rights reserved.
+ Copyright © 2015 Tom Gundersen
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
diff --git a/src/systemd/src/systemd/sd-ipv4ll.h b/src/systemd/src/systemd/sd-ipv4ll.h
index c330b0ae9e..71bd4cfe48 100644
--- a/src/systemd/src/systemd/sd-ipv4ll.h
+++ b/src/systemd/src/systemd/sd-ipv4ll.h
@@ -3,9 +3,7 @@
#define foosdipv4llfoo
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Axis Communications AB. All rights reserved.
+ Copyright © 2014 Axis Communications AB. All rights reserved.
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
diff --git a/src/systemd/src/systemd/sd-lldp.h b/src/systemd/src/systemd/sd-lldp.h
index 0a76fa6314..11a2119ab6 100644
--- a/src/systemd/src/systemd/sd-lldp.h
+++ b/src/systemd/src/systemd/sd-lldp.h
@@ -3,10 +3,8 @@
#define foosdlldphfoo
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Tom Gundersen
- Copyright (C) 2014 Susant Sahani
+ Copyright © 2014 Tom Gundersen
+ Copyright © 2014 Susant Sahani
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
diff --git a/src/systemd/src/systemd/sd-ndisc.h b/src/systemd/src/systemd/sd-ndisc.h
index 152114507a..6b6249ca03 100644
--- a/src/systemd/src/systemd/sd-ndisc.h
+++ b/src/systemd/src/systemd/sd-ndisc.h
@@ -3,9 +3,7 @@
#define foosdndiscfoo
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Intel Corporation. All rights reserved.
+ Copyright © 2014 Intel Corporation. All rights reserved.
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