summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/basic/fd-util.c6
-rw-r--r--src/basic/fs-util.c13
-rw-r--r--src/basic/khash.c275
-rw-r--r--src/basic/khash.h53
-rw-r--r--src/basic/missing.h4
-rw-r--r--src/basic/rm-rf.c15
-rw-r--r--src/basic/util.c16
-rw-r--r--src/core/killall.c3
-rw-r--r--src/core/load-fragment-gperf.gperf.m422
-rw-r--r--src/core/load-fragment.c120
-rw-r--r--src/core/manager.c14
-rw-r--r--src/core/service.c35
-rw-r--r--src/core/service.h2
-rw-r--r--src/core/socket.c8
-rw-r--r--src/core/unit-printf.c61
-rw-r--r--src/delta/delta.c10
-rw-r--r--src/libsystemd-network/network-internal.c34
-rw-r--r--src/libsystemd/libsystemd.sym5
-rw-r--r--src/libsystemd/sd-device/sd-device.c3
-rw-r--r--src/libsystemd/sd-id128/sd-id128.c32
-rw-r--r--src/libsystemd/sd-login/sd-login.c12
-rw-r--r--src/login/logind-dbus.c3
-rw-r--r--src/nspawn/nspawn.c4
-rw-r--r--src/shared/dropin.c17
-rw-r--r--src/shared/fdset.c7
-rw-r--r--src/systemd/sd-id128.h2
-rw-r--r--src/test/test-execute.c8
-rw-r--r--src/test/test-hash.c82
-rw-r--r--src/test/test-id128.c6
-rw-r--r--src/tmpfiles/tmpfiles.c15
-rw-r--r--src/udev/udev-builtin-net_id.c3
-rw-r--r--src/udev/udev-builtin-path_id.c4
-rw-r--r--src/udev/udev-node.c9
-rw-r--r--src/udev/udev-rules.c4
-rw-r--r--src/udev/udev-watch.c4
-rw-r--r--src/udev/udevadm-info.c4
36 files changed, 679 insertions, 236 deletions
diff --git a/src/basic/fd-util.c b/src/basic/fd-util.c
index 5c820332a5..19ad20789b 100644
--- a/src/basic/fd-util.c
+++ b/src/basic/fd-util.c
@@ -24,6 +24,7 @@
#include <sys/stat.h>
#include <unistd.h>
+#include "dirent-util.h"
#include "fd-util.h"
#include "fs-util.h"
#include "macro.h"
@@ -234,12 +235,9 @@ int close_all_fds(const int except[], unsigned n_except) {
return r;
}
- while ((de = readdir(d))) {
+ FOREACH_DIRENT(de, d, return -errno) {
int fd = -1;
- if (hidden_or_backup_file(de->d_name))
- continue;
-
if (safe_atoi(de->d_name, &fd) < 0)
/* Let's better ignore this, just in case */
continue;
diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c
index b30cec4f92..5b23269109 100644
--- a/src/basic/fs-util.c
+++ b/src/basic/fs-util.c
@@ -17,7 +17,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <dirent.h>
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
@@ -446,6 +445,7 @@ int mkfifo_atomic(const char *path, mode_t mode) {
int get_files_in_directory(const char *path, char ***list) {
_cleanup_closedir_ DIR *d = NULL;
+ struct dirent *de;
size_t bufsize = 0, n = 0;
_cleanup_strv_free_ char **l = NULL;
@@ -459,16 +459,7 @@ int get_files_in_directory(const char *path, char ***list) {
if (!d)
return -errno;
- for (;;) {
- struct dirent *de;
-
- errno = 0;
- de = readdir(d);
- if (!de && errno > 0)
- return -errno;
- if (!de)
- break;
-
+ FOREACH_DIRENT_ALL(de, d, return -errno) {
dirent_ensure_type(d, de);
if (!dirent_is_file(de))
diff --git a/src/basic/khash.c b/src/basic/khash.c
new file mode 100644
index 0000000000..9a2a3edb75
--- /dev/null
+++ b/src/basic/khash.c
@@ -0,0 +1,275 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2016 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <linux/if_alg.h>
+#include <stdbool.h>
+#include <sys/socket.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "hexdecoct.h"
+#include "khash.h"
+#include "macro.h"
+#include "missing.h"
+#include "string-util.h"
+#include "util.h"
+
+/* On current kernels the maximum digest (according to "grep digestsize /proc/crypto | sort -u") is actually 32, but
+ * let's add some extra room, the few wasted bytes don't really matter... */
+#define LONGEST_DIGEST 128
+
+struct khash {
+ int fd;
+ char *algorithm;
+ uint8_t digest[LONGEST_DIGEST+1];
+ size_t digest_size;
+ bool digest_valid;
+};
+
+int khash_new_with_key(khash **ret, const char *algorithm, const void *key, size_t key_size) {
+ union {
+ struct sockaddr sa;
+ struct sockaddr_alg alg;
+ } sa = {
+ .alg.salg_family = AF_ALG,
+ .alg.salg_type = "hash",
+ };
+
+ _cleanup_(khash_unrefp) khash *h = NULL;
+ _cleanup_close_ int fd = -1;
+ ssize_t n;
+
+ assert(ret);
+ assert(key || key_size == 0);
+
+ /* Filter out an empty algorithm early, as we do not support an algorithm by that name. */
+ if (isempty(algorithm))
+ return -EINVAL;
+
+ /* Overly long hash algorithm names we definitely do not support */
+ if (strlen(algorithm) >= sizeof(sa.alg.salg_name))
+ return -EOPNOTSUPP;
+
+ fd = socket(AF_ALG, SOCK_SEQPACKET|SOCK_CLOEXEC, 0);
+ if (fd < 0)
+ return -errno;
+
+ strcpy((char*) sa.alg.salg_name, algorithm);
+ if (bind(fd, &sa.sa, sizeof(sa)) < 0) {
+ if (errno == ENOENT)
+ return -EOPNOTSUPP;
+ return -errno;
+ }
+
+ if (key) {
+ if (setsockopt(fd, SOL_ALG, ALG_SET_KEY, key, key_size) < 0)
+ return -errno;
+ }
+
+ h = new0(khash, 1);
+ if (!h)
+ return -ENOMEM;
+
+ h->fd = accept4(fd, NULL, 0, SOCK_CLOEXEC);
+ if (h->fd < 0)
+ return -errno;
+
+ h->algorithm = strdup(algorithm);
+ if (!h->algorithm)
+ return -ENOMEM;
+
+ /* Temporary fix for rc kernel bug: https://bugzilla.redhat.com/show_bug.cgi?id=1395896 */
+ (void) send(h->fd, NULL, 0, 0);
+
+ /* Figure out the digest size */
+ n = recv(h->fd, h->digest, sizeof(h->digest), 0);
+ if (n < 0)
+ return -errno;
+ if (n >= LONGEST_DIGEST) /* longer than what we expected? If so, we don't support this */
+ return -EOPNOTSUPP;
+
+ h->digest_size = (size_t) n;
+ h->digest_valid = true;
+
+ /* Temporary fix for rc kernel bug: https://bugzilla.redhat.com/show_bug.cgi?id=1395896 */
+ (void) send(h->fd, NULL, 0, 0);
+
+ *ret = h;
+ h = NULL;
+
+ return 0;
+}
+
+int khash_new(khash **ret, const char *algorithm) {
+ return khash_new_with_key(ret, algorithm, NULL, 0);
+}
+
+khash* khash_unref(khash *h) {
+ if (!h)
+ return NULL;
+
+ safe_close(h->fd);
+ free(h->algorithm);
+ free(h);
+
+ return NULL;
+}
+
+int khash_dup(khash *h, khash **ret) {
+ _cleanup_(khash_unrefp) khash *copy = NULL;
+
+ assert(h);
+ assert(ret);
+
+ copy = newdup(khash, h, 1);
+ if (!copy)
+ return -ENOMEM;
+
+ copy->fd = -1;
+ copy->algorithm = strdup(h->algorithm);
+ if (!copy)
+ return -ENOMEM;
+
+ copy->fd = accept4(h->fd, NULL, 0, SOCK_CLOEXEC);
+ if (copy->fd < 0)
+ return -errno;
+
+ *ret = copy;
+ copy = NULL;
+
+ return 0;
+}
+
+const char *khash_get_algorithm(khash *h) {
+ assert(h);
+
+ return h->algorithm;
+}
+
+size_t khash_get_size(khash *h) {
+ assert(h);
+
+ return h->digest_size;
+}
+
+int khash_reset(khash *h) {
+ ssize_t n;
+
+ assert(h);
+
+ n = send(h->fd, NULL, 0, 0);
+ if (n < 0)
+ return -errno;
+
+ h->digest_valid = false;
+
+ return 0;
+}
+
+int khash_put(khash *h, const void *buffer, size_t size) {
+ ssize_t n;
+
+ assert(h);
+ assert(buffer || size == 0);
+
+ if (size <= 0)
+ return 0;
+
+ n = send(h->fd, buffer, size, MSG_MORE);
+ if (n < 0)
+ return -errno;
+
+ h->digest_valid = false;
+
+ return 0;
+}
+
+int khash_put_iovec(khash *h, const struct iovec *iovec, size_t n) {
+ struct msghdr mh = {
+ mh.msg_iov = (struct iovec*) iovec,
+ mh.msg_iovlen = n,
+ };
+ ssize_t k;
+
+ assert(h);
+ assert(iovec || n == 0);
+
+ if (n <= 0)
+ return 0;
+
+ k = sendmsg(h->fd, &mh, MSG_MORE);
+ if (k < 0)
+ return -errno;
+
+ h->digest_valid = false;
+
+ return 0;
+}
+
+static int retrieve_digest(khash *h) {
+ ssize_t n;
+
+ assert(h);
+
+ if (h->digest_valid)
+ return 0;
+
+ n = recv(h->fd, h->digest, h->digest_size, 0);
+ if (n < 0)
+ return n;
+ if ((size_t) n != h->digest_size) /* digest size changed? */
+ return -EIO;
+
+ h->digest_valid = true;
+
+ return 0;
+}
+
+int khash_digest_data(khash *h, const void **ret) {
+ int r;
+
+ assert(h);
+ assert(ret);
+
+ r = retrieve_digest(h);
+ if (r < 0)
+ return r;
+
+ *ret = h->digest;
+ return 0;
+}
+
+int khash_digest_string(khash *h, char **ret) {
+ int r;
+ char *p;
+
+ assert(h);
+ assert(ret);
+
+ r = retrieve_digest(h);
+ if (r < 0)
+ return r;
+
+ p = hexmem(h->digest, h->digest_size);
+ if (!p)
+ return -ENOMEM;
+
+ *ret = p;
+ return 0;
+}
diff --git a/src/basic/khash.h b/src/basic/khash.h
new file mode 100644
index 0000000000..f404a68236
--- /dev/null
+++ b/src/basic/khash.h
@@ -0,0 +1,53 @@
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2016 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+
+#include "macro.h"
+
+typedef struct khash khash;
+
+/* For plain hash functions. Hash functions commonly supported on today's kernels are: crc32c, crct10dif, crc32,
+ * sha224, sha256, sha512, sha384, sha1, md5, md4, sha3-224, sha3-256, sha3-384, sha3-512, and more.*/
+int khash_new(khash **ret, const char *algorithm);
+
+/* For keyed hash functions. Hash functions commonly supported on today's kernels are: hmac(sha256), cmac(aes),
+ * cmac(des3_ede), hmac(sha3-512), hmac(sha3-384), hmac(sha3-256), hmac(sha3-224), hmac(rmd160), hmac(rmd128),
+ * hmac(sha224), hmac(sha512), hmac(sha384), hmac(sha1), hmac(md5), and more. */
+int khash_new_with_key(khash **ret, const char *algorithm, const void *key, size_t key_size);
+
+int khash_dup(khash *h, khash **ret);
+khash* khash_unref(khash *h);
+
+const char *khash_get_algorithm(khash *h);
+size_t khash_get_size(khash *h);
+
+int khash_reset(khash *h);
+
+int khash_put(khash *h, const void *buffer, size_t size);
+int khash_put_iovec(khash *h, const struct iovec *iovec, size_t n);
+
+int khash_digest_data(khash *h, const void **ret);
+int khash_digest_string(khash *h, char **ret);
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(khash*, khash_unref);
diff --git a/src/basic/missing.h b/src/basic/missing.h
index 8833617dc6..1502b3f4f4 100644
--- a/src/basic/missing.h
+++ b/src/basic/missing.h
@@ -1109,4 +1109,8 @@ struct ethtool_link_settings {
#endif
+#ifndef SOL_ALG
+#define SOL_ALG 279
+#endif
+
#include "missing_syscall.h"
diff --git a/src/basic/rm-rf.c b/src/basic/rm-rf.c
index baa70c2c8d..07d42f78dd 100644
--- a/src/basic/rm-rf.c
+++ b/src/basic/rm-rf.c
@@ -17,7 +17,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
@@ -28,6 +27,7 @@
#include "btrfs-util.h"
#include "cgroup-util.h"
+#include "dirent-util.h"
#include "fd-util.h"
#include "log.h"
#include "macro.h"
@@ -43,6 +43,7 @@ static bool is_physical_fs(const struct statfs *sfs) {
int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) {
_cleanup_closedir_ DIR *d = NULL;
+ struct dirent *de;
int ret = 0, r;
struct statfs sfs;
@@ -78,19 +79,10 @@ int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) {
return errno == ENOENT ? 0 : -errno;
}
- for (;;) {
- struct dirent *de;
+ FOREACH_DIRENT_ALL(de, d, return -errno) {
bool is_dir;
struct stat st;
- errno = 0;
- de = readdir(d);
- if (!de) {
- if (errno > 0 && ret == 0)
- ret = -errno;
- return ret;
- }
-
if (streq(de->d_name, ".") || streq(de->d_name, ".."))
continue;
@@ -178,6 +170,7 @@ int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) {
}
}
}
+ return ret;
}
int rm_rf(const char *path, RemoveFlags flags) {
diff --git a/src/basic/util.c b/src/basic/util.c
index c1b5ca1ef7..8a630049d7 100644
--- a/src/basic/util.c
+++ b/src/basic/util.c
@@ -18,7 +18,6 @@
***/
#include <alloca.h>
-#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <sched.h>
@@ -508,28 +507,17 @@ void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
int on_ac_power(void) {
bool found_offline = false, found_online = false;
_cleanup_closedir_ DIR *d = NULL;
+ struct dirent *de;
d = opendir("/sys/class/power_supply");
if (!d)
return errno == ENOENT ? true : -errno;
- for (;;) {
- struct dirent *de;
+ FOREACH_DIRENT(de, d, return -errno) {
_cleanup_close_ int fd = -1, device = -1;
char contents[6];
ssize_t n;
- errno = 0;
- de = readdir(d);
- if (!de && errno > 0)
- return -errno;
-
- if (!de)
- break;
-
- if (hidden_or_backup_file(de->d_name))
- continue;
-
device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
if (device < 0) {
if (errno == ENOENT || errno == ENOTDIR)
diff --git a/src/core/killall.c b/src/core/killall.c
index 3bc19e9c84..b3aa22adc5 100644
--- a/src/core/killall.c
+++ b/src/core/killall.c
@@ -24,6 +24,7 @@
#include "alloc-util.h"
#include "def.h"
+#include "dirent-util.h"
#include "fd-util.h"
#include "format-util.h"
#include "killall.h"
@@ -172,7 +173,7 @@ static int killall(int sig, Set *pids, bool send_sighup) {
if (!dir)
return -errno;
- while ((d = readdir(dir))) {
+ FOREACH_DIRENT_ALL(d, dir, break) {
pid_t pid;
int r;
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index f4ef5a0140..2610442b91 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -191,13 +191,13 @@ Unit.IgnoreOnIsolate, config_parse_bool, 0,
Unit.IgnoreOnSnapshot, config_parse_warn_compat, DISABLED_LEGACY, 0
Unit.JobTimeoutSec, config_parse_sec_fix_0, 0, offsetof(Unit, job_timeout)
Unit.JobTimeoutAction, config_parse_emergency_action, 0, offsetof(Unit, job_timeout_action)
-Unit.JobTimeoutRebootArgument, config_parse_string, 0, offsetof(Unit, job_timeout_reboot_arg)
+Unit.JobTimeoutRebootArgument, config_parse_unit_string_printf, 0, offsetof(Unit, job_timeout_reboot_arg)
Unit.StartLimitIntervalSec, config_parse_sec, 0, offsetof(Unit, start_limit.interval)
m4_dnl The following is a legacy alias name for compatibility
Unit.StartLimitInterval, config_parse_sec, 0, offsetof(Unit, start_limit.interval)
Unit.StartLimitBurst, config_parse_unsigned, 0, offsetof(Unit, start_limit.burst)
Unit.StartLimitAction, config_parse_emergency_action, 0, offsetof(Unit, start_limit_action)
-Unit.RebootArgument, config_parse_string, 0, offsetof(Unit, reboot_arg)
+Unit.RebootArgument, config_parse_unit_string_printf, 0, offsetof(Unit, reboot_arg)
Unit.ConditionPathExists, config_parse_unit_condition_path, CONDITION_PATH_EXISTS, offsetof(Unit, conditions)
Unit.ConditionPathExistsGlob, config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB, offsetof(Unit, conditions)
Unit.ConditionPathIsDirectory, config_parse_unit_condition_path, CONDITION_PATH_IS_DIRECTORY, offsetof(Unit, conditions)
@@ -254,7 +254,7 @@ m4_dnl The following three only exist for compatibility, they moved into Unit, s
Service.StartLimitInterval, config_parse_sec, 0, offsetof(Unit, start_limit.interval)
Service.StartLimitBurst, config_parse_unsigned, 0, offsetof(Unit, start_limit.burst)
Service.StartLimitAction, config_parse_emergency_action, 0, offsetof(Unit, start_limit_action)
-Service.RebootArgument, config_parse_string, 0, offsetof(Unit, reboot_arg)
+Service.RebootArgument, config_parse_unit_path_printf, 0, offsetof(Unit, reboot_arg)
Service.FailureAction, config_parse_emergency_action, 0, offsetof(Service, emergency_action)
Service.Type, config_parse_service_type, 0, offsetof(Service, type)
Service.Restart, config_parse_service_restart, 0, offsetof(Service, restart)
@@ -272,8 +272,8 @@ Service.FileDescriptorStoreMax, config_parse_unsigned, 0,
Service.NotifyAccess, config_parse_notify_access, 0, offsetof(Service, notify_access)
Service.Sockets, config_parse_service_sockets, 0, 0
Service.BusPolicy, config_parse_warn_compat, DISABLED_LEGACY, 0
-Service.USBFunctionDescriptors, config_parse_path, 0, offsetof(Service, usb_function_descriptors)
-Service.USBFunctionStrings, config_parse_path, 0, offsetof(Service, usb_function_strings)
+Service.USBFunctionDescriptors, config_parse_unit_path_printf, 0, offsetof(Service, usb_function_descriptors)
+Service.USBFunctionStrings, config_parse_unit_path_printf, 0, offsetof(Service, usb_function_strings)
EXEC_CONTEXT_CONFIG_ITEMS(Service)m4_dnl
CGROUP_CONTEXT_CONFIG_ITEMS(Service)m4_dnl
KILL_CONTEXT_CONFIG_ITEMS(Service)m4_dnl
@@ -332,9 +332,9 @@ Socket.Service, config_parse_socket_service, 0,
Socket.TriggerLimitIntervalSec, config_parse_sec, 0, offsetof(Socket, trigger_limit.interval)
Socket.TriggerLimitBurst, config_parse_unsigned, 0, offsetof(Socket, trigger_limit.burst)
m4_ifdef(`HAVE_SMACK',
-`Socket.SmackLabel, config_parse_string, 0, offsetof(Socket, smack)
-Socket.SmackLabelIPIn, config_parse_string, 0, offsetof(Socket, smack_ip_in)
-Socket.SmackLabelIPOut, config_parse_string, 0, offsetof(Socket, smack_ip_out)',
+`Socket.SmackLabel, config_parse_unit_string_printf, 0, offsetof(Socket, smack)
+Socket.SmackLabelIPIn, config_parse_unit_string_printf, 0, offsetof(Socket, smack_ip_in)
+Socket.SmackLabelIPOut, config_parse_unit_string_printf, 0, offsetof(Socket, smack_ip_out)',
`Socket.SmackLabel, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
Socket.SmackLabelIPIn, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
Socket.SmackLabelIPOut, config_parse_warn_compat, DISABLED_CONFIGURATION, 0')
@@ -354,9 +354,9 @@ BusName.AllowWorld, config_parse_bus_policy_world, 0,
BusName.SELinuxContext, config_parse_exec_selinux_context, 0, 0
BusName.AcceptFileDescriptors, config_parse_bool, 0, offsetof(BusName, accept_fd)
m4_dnl
-Mount.What, config_parse_string, 0, offsetof(Mount, parameters_fragment.what)
+Mount.What, config_parse_unit_string_printf, 0, offsetof(Mount, parameters_fragment.what)
Mount.Where, config_parse_path, 0, offsetof(Mount, where)
-Mount.Options, config_parse_string, 0, offsetof(Mount, parameters_fragment.options)
+Mount.Options, config_parse_unit_string_printf, 0, offsetof(Mount, parameters_fragment.options)
Mount.Type, config_parse_string, 0, offsetof(Mount, parameters_fragment.fstype)
Mount.TimeoutSec, config_parse_sec, 0, offsetof(Mount, timeout_usec)
Mount.DirectoryMode, config_parse_mode, 0, offsetof(Mount, directory_mode)
@@ -373,7 +373,7 @@ Automount.TimeoutIdleSec, config_parse_sec, 0,
m4_dnl
Swap.What, config_parse_path, 0, offsetof(Swap, parameters_fragment.what)
Swap.Priority, config_parse_int, 0, offsetof(Swap, parameters_fragment.priority)
-Swap.Options, config_parse_string, 0, offsetof(Swap, parameters_fragment.options)
+Swap.Options, config_parse_unit_string_printf, 0, offsetof(Swap, parameters_fragment.options)
Swap.TimeoutSec, config_parse_sec, 0, offsetof(Swap, timeout_usec)
EXEC_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl
CGROUP_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 970eed27c1..6b36b2fc3a 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -579,6 +579,7 @@ int config_parse_exec(
void *userdata) {
ExecCommand **e = data;
+ Unit *u = userdata;
const char *p;
bool semicolon;
int r;
@@ -604,7 +605,7 @@ int config_parse_exec(
_cleanup_free_ ExecCommand *nce = NULL;
_cleanup_strv_free_ char **n = NULL;
size_t nlen = 0, nbufsize = 0;
- char *f;
+ const char *f;
int i;
semicolon = false;
@@ -631,47 +632,47 @@ int config_parse_exec(
f++;
}
- if (isempty(f)) {
+ r = unit_full_printf(u, f, &path);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring: %m", f);
+ return 0;
+ }
+
+ if (isempty(path)) {
/* First word is either "-" or "@" with no command. */
log_syntax(unit, LOG_ERR, filename, line, 0, "Empty path in command line, ignoring: \"%s\"", rvalue);
return 0;
}
- if (!string_is_safe(f)) {
+ if (!string_is_safe(path)) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Executable path contains special characters, ignoring: %s", rvalue);
return 0;
}
- if (!path_is_absolute(f)) {
+ if (!path_is_absolute(path)) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Executable path is not absolute, ignoring: %s", rvalue);
return 0;
}
- if (endswith(f, "/")) {
+ if (endswith(path, "/")) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Executable path specifies a directory, ignoring: %s", rvalue);
return 0;
}
- if (f == firstword) {
- path = firstword;
- firstword = NULL;
- } else {
- path = strdup(f);
- if (!path)
- return log_oom();
- }
-
if (!separate_argv0) {
+ char *w = NULL;
+
if (!GREEDY_REALLOC(n, nbufsize, nlen + 2))
return log_oom();
- f = strdup(path);
- if (!f)
+
+ w = strdup(path);
+ if (!w)
return log_oom();
- n[nlen++] = f;
+ n[nlen++] = w;
n[nlen] = NULL;
}
path_kill_slashes(path);
while (!isempty(p)) {
- _cleanup_free_ char *word = NULL;
+ _cleanup_free_ char *word = NULL, *resolved = NULL;
/* Check explicitly for an unquoted semicolon as
* command separator token. */
@@ -682,18 +683,21 @@ int config_parse_exec(
break;
}
- /* Check for \; explicitly, to not confuse it with \\;
- * or "\;" or "\\;" etc. extract_first_word would
- * return the same for all of those. */
+ /* Check for \; explicitly, to not confuse it with \\; or "\;" or "\\;" etc.
+ * extract_first_word() would return the same for all of those. */
if (p[0] == '\\' && p[1] == ';' && (!p[2] || strchr(WHITESPACE, p[2]))) {
+ char *w;
+
p += 2;
p += strspn(p, WHITESPACE);
+
if (!GREEDY_REALLOC(n, nbufsize, nlen + 2))
return log_oom();
- f = strdup(";");
- if (!f)
+
+ w = strdup(";");
+ if (!w)
return log_oom();
- n[nlen++] = f;
+ n[nlen++] = w;
n[nlen] = NULL;
continue;
}
@@ -701,14 +705,20 @@ int config_parse_exec(
r = extract_first_word_and_warn(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE, unit, filename, line, rvalue);
if (r == 0)
break;
- else if (r < 0)
+ if (r < 0)
return 0;
+ r = unit_full_printf(u, word, &resolved);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to resolve unit specifiers on %s, ignoring: %m", word);
+ return 0;
+ }
+
if (!GREEDY_REALLOC(n, nbufsize, nlen + 2))
return log_oom();
- n[nlen++] = word;
+ n[nlen++] = resolved;
n[nlen] = NULL;
- word = NULL;
+ resolved = NULL;
}
if (!n || !n[0]) {
@@ -1326,7 +1336,7 @@ int config_parse_exec_selinux_context(
} else
ignore = false;
- r = unit_name_printf(u, rvalue, &k);
+ r = unit_full_printf(u, rvalue, &k);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
return 0;
@@ -1374,7 +1384,7 @@ int config_parse_exec_apparmor_profile(
} else
ignore = false;
- r = unit_name_printf(u, rvalue, &k);
+ r = unit_full_printf(u, rvalue, &k);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
return 0;
@@ -1422,7 +1432,7 @@ int config_parse_exec_smack_process_label(
} else
ignore = false;
- r = unit_name_printf(u, rvalue, &k);
+ r = unit_full_printf(u, rvalue, &k);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
return 0;
@@ -1689,7 +1699,7 @@ int config_parse_fdname(
return 0;
}
- r = unit_name_printf(UNIT(s), rvalue, &p);
+ r = unit_full_printf(UNIT(s), rvalue, &p);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %s", rvalue);
return 0;
@@ -2555,7 +2565,7 @@ int config_parse_unit_requires_mounts_for(
assert(data);
for (p = rvalue;; ) {
- _cleanup_free_ char *word = NULL;
+ _cleanup_free_ char *word = NULL, *resolved = NULL;
r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
if (r == 0)
@@ -2573,9 +2583,15 @@ int config_parse_unit_requires_mounts_for(
continue;
}
- r = unit_require_mounts_for(u, word);
+ r = unit_full_printf(u, word, &resolved);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add required mount \"%s\", ignoring: %m", word);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit name \"%s\", ignoring: %m", word);
+ continue;
+ }
+
+ r = unit_require_mounts_for(u, resolved);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add required mount \"%s\", ignoring: %m", resolved);
continue;
}
}
@@ -3710,7 +3726,7 @@ int config_parse_runtime_directory(
return 0;
}
- r = unit_name_printf(u, word, &k);
+ r = unit_full_printf(u, word, &k);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to resolve specifiers in \"%s\", ignoring: %m", word);
@@ -3812,8 +3828,8 @@ int config_parse_namespace_path_strv(
void *data,
void *userdata) {
+ Unit *u = userdata;
char*** sv = data;
- const char *prev;
const char *cur;
int r;
@@ -3828,10 +3844,10 @@ int config_parse_namespace_path_strv(
return 0;
}
- prev = cur = rvalue;
+ cur = rvalue;
for (;;) {
- _cleanup_free_ char *word = NULL;
- int offset;
+ _cleanup_free_ char *word = NULL, *resolved = NULL, *joined = NULL;
+ bool ignore_enoent;
r = extract_first_word(&cur, &word, NULL, EXTRACT_QUOTES);
if (r == 0)
@@ -3839,31 +3855,37 @@ int config_parse_namespace_path_strv(
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Trailing garbage, ignoring: %s", prev);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract first word, ignoring: %s", rvalue);
return 0;
}
if (!utf8_is_valid(word)) {
log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, word);
- prev = cur;
continue;
}
- offset = word[0] == '-';
- if (!path_is_absolute(word + offset)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Not an absolute path, ignoring: %s", word);
- prev = cur;
+ ignore_enoent = word[0] == '-';
+
+ r = unit_full_printf(u, word + ignore_enoent, &resolved);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers in %s: %m", word);
+ continue;
+ }
+
+ if (!path_is_absolute(resolved)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Not an absolute path, ignoring: %s", resolved);
continue;
}
- path_kill_slashes(word + offset);
+ path_kill_slashes(resolved);
- r = strv_push(sv, word);
+ joined = strjoin(ignore_enoent ? "-" : "", resolved);
+
+ r = strv_push(sv, joined);
if (r < 0)
return log_oom();
- prev = cur;
- word = NULL;
+ joined = NULL;
}
return 0;
diff --git a/src/core/manager.c b/src/core/manager.c
index 1f663d3c1d..21cd6062c6 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -17,7 +17,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/kd.h>
@@ -233,6 +232,7 @@ static void manager_print_jobs_in_progress(Manager *m) {
static int have_ask_password(void) {
_cleanup_closedir_ DIR *dir;
+ struct dirent *de;
dir = opendir("/run/systemd/ask-password");
if (!dir) {
@@ -242,19 +242,11 @@ static int have_ask_password(void) {
return -errno;
}
- for (;;) {
- struct dirent *de;
-
- errno = 0;
- de = readdir(dir);
- if (!de && errno > 0)
- return -errno;
- if (!de)
- return false;
-
+ FOREACH_DIRENT_ALL(de, dir, return -errno) {
if (startswith(de->d_name, "ask."))
return true;
}
+ return false;
}
static int manager_dispatch_ask_password_fd(sd_event_source *source,
diff --git a/src/core/service.c b/src/core/service.c
index c68a7122b6..576416ad29 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -49,7 +49,6 @@
#include "string-util.h"
#include "strv.h"
#include "unit-name.h"
-#include "unit-printf.h"
#include "unit.h"
#include "utf8.h"
#include "util.h"
@@ -1205,7 +1204,7 @@ static int service_spawn(
ExecFlags flags,
pid_t *_pid) {
- _cleanup_strv_free_ char **argv = NULL, **final_env = NULL, **our_env = NULL, **fd_names = NULL;
+ _cleanup_strv_free_ char **final_env = NULL, **our_env = NULL, **fd_names = NULL;
_cleanup_free_ int *fds = NULL;
unsigned n_fds = 0, n_env = 0;
const char *path;
@@ -1263,10 +1262,6 @@ static int service_spawn(
if (r < 0)
return r;
- r = unit_full_printf_strv(UNIT(s), c->argv, &argv);
- if (r < 0)
- return r;
-
our_env = new0(char*, 9);
if (!our_env)
return -ENOMEM;
@@ -1349,7 +1344,7 @@ static int service_spawn(
} else
path = UNIT(s)->cgroup_path;
- exec_params.argv = argv;
+ exec_params.argv = c->argv;
exec_params.environment = final_env;
exec_params.fds = fds;
exec_params.fd_names = fd_names;
@@ -1714,7 +1709,7 @@ static void service_enter_running(Service *s, ServiceResult f) {
}
} else if (f != SERVICE_SUCCESS)
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, f);
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, f);
else if (s->remain_after_exit)
service_set_state(s, SERVICE_EXITED);
else
@@ -1851,7 +1846,7 @@ static void service_enter_start(Service *s) {
fail:
log_unit_warning_errno(UNIT(s), r, "Failed to run 'start' task: %m");
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_RESOURCES);
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES);
}
static void service_enter_start_pre(Service *s) {
@@ -1997,9 +1992,7 @@ static void service_run_next_control(Service *s) {
fail:
log_unit_warning_errno(UNIT(s), r, "Failed to run next control task: %m");
- if (s->state == SERVICE_START_PRE)
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_RESOURCES);
- else if (s->state == SERVICE_STOP)
+ if (IN_SET(s->state, SERVICE_START_PRE, SERVICE_STOP))
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES);
else if (s->state == SERVICE_STOP_POST)
service_enter_dead(s, SERVICE_FAILURE_RESOURCES, true);
@@ -2600,7 +2593,7 @@ static void service_notify_cgroup_empty_event(Unit *u) {
case SERVICE_START:
if (s->type == SERVICE_NOTIFY) {
/* No chance of getting a ready notification anymore */
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_PROTOCOL);
+ service_enter_stop_post(s, SERVICE_FAILURE_PROTOCOL);
break;
}
@@ -2613,7 +2606,7 @@ static void service_notify_cgroup_empty_event(Unit *u) {
service_unwatch_pid_file(s);
if (s->state == SERVICE_START)
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_PROTOCOL);
+ service_enter_stop_post(s, SERVICE_FAILURE_PROTOCOL);
else
service_enter_stop(s, SERVICE_FAILURE_PROTOCOL);
}
@@ -2747,17 +2740,17 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
if (f == SERVICE_SUCCESS)
service_enter_start_post(s);
else
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, f);
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, f);
break;
} else if (s->type == SERVICE_NOTIFY) {
/* Only enter running through a notification, so that the
* SERVICE_START state signifies that no ready notification
* has been received */
if (f != SERVICE_SUCCESS)
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, f);
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, f);
else if (!s->remain_after_exit)
/* The service has never been active */
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_PROTOCOL);
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_PROTOCOL);
break;
}
@@ -2837,7 +2830,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
if (f == SERVICE_SUCCESS)
service_enter_start(s);
else
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, f);
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, f);
break;
case SERVICE_START:
@@ -2846,7 +2839,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
break;
if (f != SERVICE_SUCCESS) {
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, f);
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, f);
break;
}
@@ -2863,7 +2856,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
if (!has_start_post && r < 0) {
r = service_demand_pid_file(s);
if (r < 0 || !cgroup_good(s))
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_PROTOCOL);
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_PROTOCOL);
break;
}
} else
@@ -2959,7 +2952,7 @@ static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *us
case SERVICE_START_PRE:
case SERVICE_START:
log_unit_warning(UNIT(s), "%s operation timed out. Terminating.", s->state == SERVICE_START ? "Start" : "Start-pre");
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_TIMEOUT);
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_TIMEOUT);
break;
case SERVICE_START_POST:
diff --git a/src/core/service.h b/src/core/service.h
index e09722a952..ff9cfaeb88 100644
--- a/src/core/service.h
+++ b/src/core/service.h
@@ -79,6 +79,8 @@ typedef enum NotifyState {
_NOTIFY_STATE_INVALID = -1
} NotifyState;
+/* The values of this enum are referenced in man/systemd.exec.xml and src/shared/bus-unit-util.c.
+ * Update those sources for each change to this enum. */
typedef enum ServiceResult {
SERVICE_SUCCESS,
SERVICE_FAILURE_RESOURCES, /* a bit of a misnomer, just our catch-all error for errnos we didn't expect */
diff --git a/src/core/socket.c b/src/core/socket.c
index 1a53d47f21..fee9b702e6 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -54,7 +54,6 @@
#include "string-util.h"
#include "strv.h"
#include "unit-name.h"
-#include "unit-printf.h"
#include "unit.h"
#include "user-util.h"
#include "in-addr-util.h"
@@ -1740,7 +1739,6 @@ static int socket_coldplug(Unit *u) {
}
static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
- _cleanup_free_ char **argv = NULL;
pid_t pid;
int r;
ExecParameters exec_params = {
@@ -1772,11 +1770,7 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
if (r < 0)
return r;
- r = unit_full_printf_strv(UNIT(s), c->argv, &argv);
- if (r < 0)
- return r;
-
- exec_params.argv = argv;
+ exec_params.argv = c->argv;
exec_params.environment = UNIT(s)->manager->environment;
exec_params.confirm_spawn = manager_get_confirm_spawn(UNIT(s)->manager);
exec_params.cgroup_supported = UNIT(s)->manager->cgroup_supported;
diff --git a/src/core/unit-printf.c b/src/core/unit-printf.c
index 1f5dc6fd88..746e1a46ef 100644
--- a/src/core/unit-printf.c
+++ b/src/core/unit-printf.c
@@ -78,12 +78,18 @@ static int specifier_filename(char specifier, void *data, void *userdata, char *
return unit_name_to_path(u->id, ret);
}
+static void bad_specifier(Unit *u, char specifier) {
+ log_unit_warning(u, "Specifier '%%%c' used in unit configuration, which is deprecated. Please update your unit file, as it does not work as intended.", specifier);
+}
+
static int specifier_cgroup(char specifier, void *data, void *userdata, char **ret) {
Unit *u = userdata;
char *n;
assert(u);
+ bad_specifier(u, specifier);
+
if (u->cgroup_path)
n = strdup(u->cgroup_path);
else
@@ -101,6 +107,8 @@ static int specifier_cgroup_root(char specifier, void *data, void *userdata, cha
assert(u);
+ bad_specifier(u, specifier);
+
n = strdup(u->manager->cgroup_root);
if (!n)
return -ENOMEM;
@@ -115,6 +123,8 @@ static int specifier_cgroup_slice(char specifier, void *data, void *userdata, ch
assert(u);
+ bad_specifier(u, specifier);
+
if (UNIT_ISSET(u->slice)) {
Unit *slice;
@@ -194,13 +204,20 @@ static int specifier_user_shell(char specifier, void *data, void *userdata, char
int unit_name_printf(Unit *u, const char* format, char **ret) {
/*
- * This will use the passed string as format string and
- * replace the following specifiers:
+ * This will use the passed string as format string and replace the following specifiers (which should all be
+ * safe for inclusion in unit names):
*
* %n: the full id of the unit (foo@bar.waldo)
* %N: the id of the unit without the suffix (foo@bar)
* %p: the prefix (foo)
* %i: the instance (bar)
+ *
+ * %U: the UID of the running user
+ * %u: the username of the running user
+ *
+ * %m: the machine ID of the running system
+ * %H: the host name of the running system
+ * %b: the boot ID of the running system
*/
const Specifier table[] = {
@@ -208,7 +225,14 @@ int unit_name_printf(Unit *u, const char* format, char **ret) {
{ 'N', specifier_prefix_and_instance, NULL },
{ 'p', specifier_prefix, NULL },
{ 'i', specifier_string, u->instance },
- { 0, NULL, NULL }
+
+ { 'U', specifier_user_id, NULL },
+ { 'u', specifier_user_name, NULL },
+
+ { 'm', specifier_machine_id, NULL },
+ { 'H', specifier_host_name, NULL },
+ { 'b', specifier_boot_id, NULL },
+ {}
};
assert(u);
@@ -220,22 +244,23 @@ int unit_name_printf(Unit *u, const char* format, char **ret) {
int unit_full_printf(Unit *u, const char *format, char **ret) {
- /* This is similar to unit_name_printf() but also supports
- * unescaping. Also, adds a couple of additional codes:
+ /* This is similar to unit_name_printf() but also supports unescaping. Also, adds a couple of additional codes
+ * (which are likely not suitable for unescaped inclusion in unit names):
+ *
+ * %f: the unescaped instance if set, otherwise the id unescaped as path
+ * %c: cgroup path of unit (deprecated)
+ * %r: where units in this slice are placed in the cgroup tree (deprecated)
+ * %R: the root of this systemd's instance tree (deprecated)
+ * %t: the runtime directory to place sockets in (e.g. "/run" or $XDG_RUNTIME_DIR)
+ *
+ * %h: the homedir of the running user
+ * %s: the shell of the running user
+ *
+ * %v: `uname -r` of the running system
*
- * %f the instance if set, otherwise the id
- * %c cgroup path of unit
- * %r where units in this slice are placed in the cgroup tree
- * %R the root of this systemd's instance tree
- * %t the runtime directory to place sockets in (e.g. "/run" or $XDG_RUNTIME_DIR)
- * %U the UID of the running user
- * %u the username of the running user
- * %h the homedir of the running user
- * %s the shell of the running user
- * %m the machine ID of the running system
- * %H the host name of the running system
- * %b the boot ID of the running system
- * %v `uname -r` of the running system
+ * NOTICE: When you add new entries here, please be careful: specifiers which depend on settings of the unit
+ * file itself are broken by design, as they would resolve differently depending on whether they are used
+ * before or after the relevant configuration setting. Hence: don't add them.
*/
const Specifier table[] = {
diff --git a/src/delta/delta.c b/src/delta/delta.c
index 107b105fde..9a44b15da7 100644
--- a/src/delta/delta.c
+++ b/src/delta/delta.c
@@ -297,6 +297,7 @@ static int enumerate_dir_d(Hashmap *top, Hashmap *bottom, Hashmap *drops, const
static int enumerate_dir(Hashmap *top, Hashmap *bottom, Hashmap *drops, const char *path, bool dropins) {
_cleanup_closedir_ DIR *d;
+ struct dirent *de;
assert(top);
assert(bottom);
@@ -313,16 +314,10 @@ static int enumerate_dir(Hashmap *top, Hashmap *bottom, Hashmap *drops, const ch
return log_error_errno(errno, "Failed to open %s: %m", path);
}
- for (;;) {
- struct dirent *de;
+ FOREACH_DIRENT_ALL(de, d, return -errno) {
int k;
char *p;
- errno = 0;
- de = readdir(d);
- if (!de)
- return -errno;
-
dirent_ensure_type(d, de);
if (dropins && de->d_type == DT_DIR && endswith(de->d_name, ".d"))
@@ -354,6 +349,7 @@ static int enumerate_dir(Hashmap *top, Hashmap *bottom, Hashmap *drops, const ch
return k;
}
}
+ return 0;
}
static int should_skip_prefix(const char* p) {
diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c
index 9d78b953fc..092a1eabb0 100644
--- a/src/libsystemd-network/network-internal.c
+++ b/src/libsystemd-network/network-internal.c
@@ -86,6 +86,28 @@ int net_get_unique_predictable_data(struct udev_device *device, uint64_t *result
return 0;
}
+static bool net_condition_test_strv(char * const *raw_patterns,
+ const char *string) {
+ if (strv_isempty(raw_patterns))
+ return true;
+
+ /* If the patterns begin with "!", edit it out and negate the test. */
+ if (raw_patterns[0][0] == '!') {
+ char **patterns;
+ unsigned i, length;
+
+ length = strv_length(raw_patterns) + 1; /* Include the NULL. */
+ patterns = newa(char*, length);
+ patterns[0] = raw_patterns[0] + 1; /* Skip the "!". */
+ for (i = 1; i < length; i++)
+ patterns[i] = raw_patterns[i];
+
+ return !string || !strv_fnmatch(patterns, string, 0);
+ }
+
+ return string && strv_fnmatch(raw_patterns, string, 0);
+}
+
bool net_match_config(const struct ether_addr *match_mac,
char * const *match_paths,
char * const *match_drivers,
@@ -117,20 +139,16 @@ bool net_match_config(const struct ether_addr *match_mac,
if (match_mac && (!dev_mac || memcmp(match_mac, dev_mac, ETH_ALEN)))
return false;
- if (!strv_isempty(match_paths) &&
- (!dev_path || !strv_fnmatch(match_paths, dev_path, 0)))
+ if (!net_condition_test_strv(match_paths, dev_path))
return false;
- if (!strv_isempty(match_drivers) &&
- (!dev_driver || !strv_fnmatch(match_drivers, dev_driver, 0)))
+ if (!net_condition_test_strv(match_drivers, dev_driver))
return false;
- if (!strv_isempty(match_types) &&
- (!dev_type || !strv_fnmatch_or_empty(match_types, dev_type, 0)))
+ if (!net_condition_test_strv(match_types, dev_type))
return false;
- if (!strv_isempty(match_names) &&
- (!dev_name || !strv_fnmatch_or_empty(match_names, dev_name, 0)))
+ if (!net_condition_test_strv(match_names, dev_name))
return false;
return true;
diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym
index d48ef6bbe2..46c4dac7d7 100644
--- a/src/libsystemd/libsystemd.sym
+++ b/src/libsystemd/libsystemd.sym
@@ -511,3 +511,8 @@ global:
sd_bus_get_exit_on_disconnect;
sd_id128_get_invocation;
} LIBSYSTEMD_231;
+
+LIBSYSTEMD_233 {
+global:
+ sd_id128_get_machine_app_specific;
+} LIBSYSTEMD_232;
diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c
index 1081979bf9..bc5e92f8fe 100644
--- a/src/libsystemd/sd-device/sd-device.c
+++ b/src/libsystemd/sd-device/sd-device.c
@@ -28,6 +28,7 @@
#include "device-internal.h"
#include "device-private.h"
#include "device-util.h"
+#include "dirent-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
@@ -1627,7 +1628,7 @@ static int device_sysattrs_read_all(sd_device *device) {
if (r < 0)
return r;
- for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
+ FOREACH_DIRENT_ALL(dent, dir, return -errno) {
char *path;
struct stat statbuf;
diff --git a/src/libsystemd/sd-id128/sd-id128.c b/src/libsystemd/sd-id128/sd-id128.c
index d4450c70a0..0d673ba655 100644
--- a/src/libsystemd/sd-id128/sd-id128.c
+++ b/src/libsystemd/sd-id128/sd-id128.c
@@ -27,6 +27,7 @@
#include "hexdecoct.h"
#include "id128-util.h"
#include "io-util.h"
+#include "khash.h"
#include "macro.h"
#include "random-util.h"
#include "util.h"
@@ -181,3 +182,34 @@ _public_ int sd_id128_randomize(sd_id128_t *ret) {
*ret = make_v4_uuid(t);
return 0;
}
+
+_public_ int sd_id128_get_machine_app_specific(sd_id128_t app_id, sd_id128_t *ret) {
+ _cleanup_(khash_unrefp) khash *h = NULL;
+ sd_id128_t m, result;
+ const void *p;
+ int r;
+
+ assert_return(ret, -EINVAL);
+
+ r = sd_id128_get_machine(&m);
+ if (r < 0)
+ return r;
+
+ r = khash_new_with_key(&h, "hmac(sha256)", &m, sizeof(m));
+ if (r < 0)
+ return r;
+
+ r = khash_put(h, &app_id, sizeof(app_id));
+ if (r < 0)
+ return r;
+
+ r = khash_digest_data(h, &p);
+ if (r < 0)
+ return r;
+
+ /* We chop off the trailing 16 bytes */
+ memcpy(&result, p, MIN(khash_get_size(h), sizeof(result)));
+
+ *ret = make_v4_uuid(result);
+ return 0;
+}
diff --git a/src/libsystemd/sd-login/sd-login.c b/src/libsystemd/sd-login/sd-login.c
index 42ea0badfc..d2cfbdf5b0 100644
--- a/src/libsystemd/sd-login/sd-login.c
+++ b/src/libsystemd/sd-login/sd-login.c
@@ -793,6 +793,7 @@ _public_ int sd_get_sessions(char ***sessions) {
_public_ int sd_get_uids(uid_t **users) {
_cleanup_closedir_ DIR *d;
+ struct dirent *de;
int r = 0;
unsigned n = 0;
_cleanup_free_ uid_t *l = NULL;
@@ -801,19 +802,10 @@ _public_ int sd_get_uids(uid_t **users) {
if (!d)
return -errno;
- for (;;) {
- struct dirent *de;
+ FOREACH_DIRENT_ALL(de, d, return -errno) {
int k;
uid_t uid;
- errno = 0;
- de = readdir(d);
- if (!de && errno > 0)
- return -errno;
-
- if (!de)
- break;
-
dirent_ensure_type(d, de);
if (!dirent_is_file(de))
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 23ad5d7c6a..3873bf3e96 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -1286,8 +1286,7 @@ static int flush_devices(Manager *m) {
} else {
struct dirent *de;
- while ((de = readdir(d))) {
-
+ FOREACH_DIRENT_ALL(de, d, break) {
if (!dirent_is_file(de))
continue;
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index de05b6c5ef..d701f2158d 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -490,7 +490,7 @@ static int parse_argv(int argc, char *argv[]) {
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "+hD:u:abL:M:jS:Z:qi:xp:nU", options, NULL)) >= 0)
+ while ((c = getopt_long(argc, argv, "+hD:u:abL:M:jS:Z:qi:xp:nUE:", options, NULL)) >= 0)
switch (c) {
@@ -1326,6 +1326,8 @@ static int setup_resolv_conf(const char *dest) {
* advantage that the container will be able to follow the host's DNS server configuration changes
* transparently. */
+ (void) touch(where);
+
r = mount_verbose(LOG_WARNING, "/usr/lib/systemd/resolv.conf", where, NULL, MS_BIND, NULL);
if (r >= 0)
return mount_verbose(LOG_ERR, NULL, where, NULL,
diff --git a/src/shared/dropin.c b/src/shared/dropin.c
index 2c1cd84df5..3cbfe13f4c 100644
--- a/src/shared/dropin.c
+++ b/src/shared/dropin.c
@@ -17,7 +17,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <dirent.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
@@ -25,6 +24,7 @@
#include "alloc-util.h"
#include "conf-files.h"
+#include "dirent-util.h"
#include "dropin.h"
#include "escape.h"
#include "fd-util.h"
@@ -124,6 +124,7 @@ static int iterate_dir(
char ***strv) {
_cleanup_closedir_ DIR *d = NULL;
+ struct dirent *de;
int r;
assert(path);
@@ -148,21 +149,9 @@ static int iterate_dir(
return log_error_errno(errno, "Failed to open directory %s: %m", path);
}
- for (;;) {
- struct dirent *de;
+ FOREACH_DIRENT(de, d, return log_error_errno(errno, "Failed to read directory %s: %m", path)) {
_cleanup_free_ char *f = NULL;
- errno = 0;
- de = readdir(d);
- if (!de && errno > 0)
- return log_error_errno(errno, "Failed to read directory %s: %m", path);
-
- if (!de)
- break;
-
- if (hidden_or_backup_file(de->d_name))
- continue;
-
f = strjoin(path, "/", de->d_name);
if (!f)
return log_oom();
diff --git a/src/shared/fdset.c b/src/shared/fdset.c
index 527f27bc67..090f3fdcdd 100644
--- a/src/shared/fdset.c
+++ b/src/shared/fdset.c
@@ -18,13 +18,13 @@
***/
#include <alloca.h>
-#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stddef.h>
#include "sd-daemon.h"
+#include "dirent-util.h"
#include "fd-util.h"
#include "fdset.h"
#include "log.h"
@@ -148,12 +148,9 @@ int fdset_new_fill(FDSet **_s) {
goto finish;
}
- while ((de = readdir(d))) {
+ FOREACH_DIRENT(de, d, return -errno) {
int fd = -1;
- if (hidden_or_backup_file(de->d_name))
- continue;
-
r = safe_atoi(de->d_name, &fd);
if (r < 0)
goto finish;
diff --git a/src/systemd/sd-id128.h b/src/systemd/sd-id128.h
index ee011b1861..6cc8e4ac0e 100644
--- a/src/systemd/sd-id128.h
+++ b/src/systemd/sd-id128.h
@@ -39,12 +39,12 @@ union sd_id128 {
#define SD_ID128_STRING_MAX 33
char *sd_id128_to_string(sd_id128_t id, char s[SD_ID128_STRING_MAX]);
-
int sd_id128_from_string(const char *s, sd_id128_t *ret);
int sd_id128_randomize(sd_id128_t *ret);
int sd_id128_get_machine(sd_id128_t *ret);
+int sd_id128_get_machine_app_specific(sd_id128_t app_id, sd_id128_t *ret);
int sd_id128_get_boot(sd_id128_t *ret);
int sd_id128_get_invocation(sd_id128_t *ret);
diff --git a/src/test/test-execute.c b/src/test/test-execute.c
index b2ea358b8c..4670458ffb 100644
--- a/src/test/test-execute.c
+++ b/src/test/test-execute.c
@@ -409,8 +409,8 @@ static void test_exec_spec_interpolation(Manager *m) {
test(m, "exec-spec-interpolation.service", 0, CLD_EXITED);
}
-static int run_tests(UnitFileScope scope, test_function_t *tests) {
- test_function_t *test = NULL;
+static int run_tests(UnitFileScope scope, const test_function_t *tests) {
+ const test_function_t *test = NULL;
Manager *m = NULL;
int r;
@@ -433,7 +433,7 @@ static int run_tests(UnitFileScope scope, test_function_t *tests) {
}
int main(int argc, char *argv[]) {
- test_function_t user_tests[] = {
+ static const test_function_t user_tests[] = {
test_exec_workingdirectory,
test_exec_personality,
test_exec_ignoresigpipe,
@@ -464,7 +464,7 @@ int main(int argc, char *argv[]) {
test_exec_spec_interpolation,
NULL,
};
- test_function_t system_tests[] = {
+ static const test_function_t system_tests[] = {
test_exec_systemcall_system_mode_with_user,
NULL,
};
diff --git a/src/test/test-hash.c b/src/test/test-hash.c
new file mode 100644
index 0000000000..1972b94cfe
--- /dev/null
+++ b/src/test/test-hash.c
@@ -0,0 +1,82 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2016 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "alloc-util.h"
+#include "log.h"
+#include "string-util.h"
+#include "khash.h"
+
+int main(int argc, char *argv[]) {
+ _cleanup_(khash_unrefp) khash *h = NULL, *copy = NULL;
+ _cleanup_free_ char *s = NULL;
+
+ log_set_max_level(LOG_DEBUG);
+
+ assert_se(khash_new(&h, NULL) == -EINVAL);
+ assert_se(khash_new(&h, "") == -EINVAL);
+ assert_se(khash_new(&h, "foobar") == -EOPNOTSUPP);
+
+ assert_se(khash_new(&h, "sha256") >= 0);
+ assert_se(khash_get_size(h) == 32);
+ assert_se(streq(khash_get_algorithm(h), "sha256"));
+
+ assert_se(khash_digest_string(h, &s) >= 0);
+ assert_se(streq(s, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"));
+ s = mfree(s);
+
+ assert_se(khash_put(h, "foobar", 6) >= 0);
+ assert_se(khash_digest_string(h, &s) >= 0);
+ assert_se(streq(s, "c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2"));
+ s = mfree(s);
+
+ assert_se(khash_put(h, "piep", 4) >= 0);
+ assert_se(khash_digest_string(h, &s) >= 0);
+ assert_se(streq(s, "f114d872b5ea075d3be9040d0b7a429514b3f9324a8e8e3dc3fb24c34ee56bea"));
+ s = mfree(s);
+
+ assert_se(khash_put(h, "foo", 3) >= 0);
+ assert_se(khash_dup(h, &copy) >= 0);
+
+ assert_se(khash_put(h, "bar", 3) >= 0);
+ assert_se(khash_put(copy, "bar", 3) >= 0);
+
+ assert_se(khash_digest_string(h, &s) >= 0);
+ assert_se(streq(s, "c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2"));
+ s = mfree(s);
+
+ assert_se(khash_digest_string(copy, &s) >= 0);
+ assert_se(streq(s, "c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2"));
+ s = mfree(s);
+
+ h = khash_unref(h);
+
+ assert_se(khash_new_with_key(&h, "hmac(sha256)", "quux", 4) >= 0);
+ assert_se(khash_get_size(h) == 32);
+ assert_se(streq(khash_get_algorithm(h), "hmac(sha256)"));
+
+ assert_se(khash_digest_string(h, &s) >= 0);
+ assert_se(streq(s, "abed9f8218ab473f77218a6a7d39abf1d21fa46d0700c4898e330ba88309d5ae"));
+ s = mfree(s);
+
+ assert_se(khash_put(h, "foobar", 6) >= 0);
+ assert_se(khash_digest_string(h, &s) >= 0);
+ assert_se(streq(s, "33f6c70a60db66007d5325d5d1dea37c371354e5b83347a59ad339ce9f4ba3dc"));
+
+ return 0;
+}
diff --git a/src/test/test-id128.c b/src/test/test-id128.c
index 1c8e5549da..ab5a111ba9 100644
--- a/src/test/test-id128.c
+++ b/src/test/test-id128.c
@@ -153,5 +153,11 @@ int main(int argc, char *argv[]) {
assert_se(id128_read_fd(fd, ID128_UUID, &id2) >= 0);
assert_se(sd_id128_equal(id, id2));
+ assert_se(sd_id128_get_machine_app_specific(SD_ID128_MAKE(f0,3d,aa,eb,1c,33,4b,43,a7,32,17,29,44,bf,77,2e), &id) >= 0);
+ assert_se(sd_id128_get_machine_app_specific(SD_ID128_MAKE(f0,3d,aa,eb,1c,33,4b,43,a7,32,17,29,44,bf,77,2e), &id2) >= 0);
+ assert_se(sd_id128_equal(id, id2));
+ assert_se(sd_id128_get_machine_app_specific(SD_ID128_MAKE(51,df,0b,4b,c3,b0,4c,97,80,e2,99,b9,8c,a3,73,b8), &id2) >= 0);
+ assert_se(!sd_id128_equal(id, id2));
+
return 0;
}
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index b881d774a0..79f75e165b 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -18,7 +18,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <fnmatch.h>
@@ -44,6 +43,7 @@
#include "conf-files.h"
#include "copy.h"
#include "def.h"
+#include "dirent-util.h"
#include "escape.h"
#include "fd-util.h"
#include "fileio.h"
@@ -380,7 +380,7 @@ static int dir_cleanup(
bool deleted = false;
int r = 0;
- while ((dent = readdir(d))) {
+ FOREACH_DIRENT_ALL(dent, d, break) {
struct stat s;
usec_t age;
_cleanup_free_ char *sub_path = NULL;
@@ -1053,6 +1053,7 @@ typedef int (*action_t)(Item *, const char *);
static int item_do_children(Item *i, const char *path, action_t action) {
_cleanup_closedir_ DIR *d;
+ struct dirent *de;
int r = 0;
assert(i);
@@ -1065,19 +1066,11 @@ static int item_do_children(Item *i, const char *path, action_t action) {
if (!d)
return errno == ENOENT || errno == ENOTDIR ? 0 : -errno;
- for (;;) {
+ FOREACH_DIRENT_ALL(de, d, r = -errno) {
_cleanup_free_ char *p = NULL;
- struct dirent *de;
int q;
errno = 0;
- de = readdir(d);
- if (!de) {
- if (errno > 0 && r == 0)
- r = -errno;
-
- break;
- }
if (STR_IN_SET(de->d_name, ".", ".."))
continue;
diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c
index fe9d6f4482..5be158f527 100644
--- a/src/udev/udev-builtin-net_id.c
+++ b/src/udev/udev-builtin-net_id.c
@@ -100,6 +100,7 @@
#include <unistd.h>
#include <linux/pci_regs.h>
+#include "dirent-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "stdio-util.h"
@@ -256,7 +257,7 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
goto out;
}
- for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
+ FOREACH_DIRENT_ALL(dent, dir, break) {
int i;
char *rest, *address, str[PATH_MAX];
diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c
index 1825ee75a7..527f0bff2d 100644
--- a/src/udev/udev-builtin-path_id.c
+++ b/src/udev/udev-builtin-path_id.c
@@ -20,7 +20,6 @@
*/
#include <ctype.h>
-#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
@@ -31,6 +30,7 @@
#include <unistd.h>
#include "alloc-util.h"
+#include "dirent-util.h"
#include "string-util.h"
#include "udev.h"
@@ -405,7 +405,7 @@ static struct udev_device *handle_scsi_default(struct udev_device *parent, char
parent = NULL;
goto out;
}
- for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
+ FOREACH_DIRENT_ALL(dent, dir, break) {
char *rest;
int i;
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
index e94a814388..53cfd9c053 100644
--- a/src/udev/udev-node.c
+++ b/src/udev/udev-node.c
@@ -15,7 +15,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
@@ -25,6 +24,7 @@
#include <sys/stat.h>
#include <unistd.h>
+#include "dirent-util.h"
#include "format-util.h"
#include "fs-util.h"
#include "selinux-util.h"
@@ -129,6 +129,7 @@ exit:
static const char *link_find_prioritized(struct udev_device *dev, bool add, const char *stackdir, char *buf, size_t bufsize) {
struct udev *udev = udev_device_get_udev(dev);
DIR *dir;
+ struct dirent *dent;
int priority = 0;
const char *target = NULL;
@@ -141,12 +142,10 @@ static const char *link_find_prioritized(struct udev_device *dev, bool add, cons
dir = opendir(stackdir);
if (dir == NULL)
return target;
- for (;;) {
+ FOREACH_DIRENT_ALL(dent, dir, break) {
struct udev_device *dev_db;
- struct dirent *dent;
- dent = readdir(dir);
- if (dent == NULL || dent->d_name[0] == '\0')
+ if (dent->d_name[0] == '\0')
break;
if (dent->d_name[0] == '.')
continue;
diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c
index d88687e9c2..b0238220e4 100644
--- a/src/udev/udev-rules.c
+++ b/src/udev/udev-rules.c
@@ -16,7 +16,6 @@
*/
#include <ctype.h>
-#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <fnmatch.h>
@@ -31,6 +30,7 @@
#include "alloc-util.h"
#include "conf-files.h"
+#include "dirent-util.h"
#include "escape.h"
#include "fd-util.h"
#include "fs-util.h"
@@ -703,7 +703,7 @@ static void attr_subst_subdir(char *attr, size_t len) {
if (dir == NULL)
return;
- for (dent = readdir(dir); dent != NULL; dent = readdir(dir))
+ FOREACH_DIRENT_ALL(dent, dir, break)
if (dent->d_name[0] != '.') {
char n[strlen(dent->d_name) + strlen(tail) + 1];
diff --git a/src/udev/udev-watch.c b/src/udev/udev-watch.c
index bc9096ed0c..aa432bb90a 100644
--- a/src/udev/udev-watch.c
+++ b/src/udev/udev-watch.c
@@ -17,13 +17,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <dirent.h>
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#include <sys/inotify.h>
#include <unistd.h>
+#include "dirent-util.h"
#include "stdio-util.h"
#include "udev.h"
@@ -57,7 +57,7 @@ void udev_watch_restore(struct udev *udev) {
return;
}
- for (ent = readdir(dir); ent != NULL; ent = readdir(dir)) {
+ FOREACH_DIRENT_ALL(ent, dir, break) {
char device[UTIL_PATH_SIZE];
ssize_t len;
struct udev_device *dev;
diff --git a/src/udev/udevadm-info.c b/src/udev/udevadm-info.c
index 6753c52005..90cdfa16c7 100644
--- a/src/udev/udevadm-info.c
+++ b/src/udev/udevadm-info.c
@@ -16,7 +16,6 @@
*/
#include <ctype.h>
-#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
@@ -26,6 +25,7 @@
#include <sys/stat.h>
#include <unistd.h>
+#include "dirent-util.h"
#include "fd-util.h"
#include "string-util.h"
#include "udev-util.h"
@@ -196,7 +196,7 @@ static void cleanup_dir(DIR *dir, mode_t mask, int depth) {
if (depth <= 0)
return;
- for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
+ FOREACH_DIRENT_ALL(dent, dir, break) {
struct stat stats;
if (dent->d_name[0] == '.')