summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/basic/cgroup-util.c3
-rw-r--r--src/basic/copy.c2
-rw-r--r--src/basic/hexdecoct.c4
-rw-r--r--src/basic/path-util.c25
-rw-r--r--src/basic/path-util.h2
-rw-r--r--src/basic/rm-rf.c2
-rw-r--r--src/basic/socket-util.c2
-rw-r--r--src/boot/efi/boot.c2
-rw-r--r--src/boot/efi/stub.c2
-rw-r--r--src/cgls/cgls.c160
-rw-r--r--src/cgtop/cgtop.c67
-rw-r--r--src/core/execute.c62
-rw-r--r--src/core/killall.c29
-rw-r--r--src/core/timer.c2
-rw-r--r--src/cryptsetup/cryptsetup.c4
-rw-r--r--src/gpt-auto-generator/gpt-auto-generator.c2
-rw-r--r--src/journal/journal-file.c84
-rw-r--r--src/journal/journalctl.c4
-rw-r--r--src/login/loginctl.c25
-rw-r--r--src/login/logind-dbus.c10
-rw-r--r--src/machine/machinectl.c24
-rw-r--r--src/nspawn/nspawn-patch-uid.c2
-rw-r--r--src/resolve/resolved-manager.c2
-rw-r--r--src/shared/cgroup-show.c86
-rw-r--r--src/shared/cgroup-show.h11
-rw-r--r--src/shared/clean-ipc.c4
-rw-r--r--src/system-update-generator/system-update-generator.c25
-rw-r--r--src/systemctl/systemctl.c1
-rw-r--r--src/test/test-fs-util.c11
-rw-r--r--src/tmpfiles/tmpfiles.c6
30 files changed, 389 insertions, 276 deletions
diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c
index d2d18f13f0..6948ed3931 100644
--- a/src/basic/cgroup-util.c
+++ b/src/basic/cgroup-util.c
@@ -182,8 +182,7 @@ int cg_read_subgroup(DIR *d, char **fn) {
if (de->d_type != DT_DIR)
continue;
- if (streq(de->d_name, ".") ||
- streq(de->d_name, ".."))
+ if (dot_or_dot_dot(de->d_name))
continue;
b = strdup(de->d_name);
diff --git a/src/basic/copy.c b/src/basic/copy.c
index 9883f5fa31..e9a7efd232 100644
--- a/src/basic/copy.c
+++ b/src/basic/copy.c
@@ -331,7 +331,7 @@ static int fd_copy_directory(
struct stat buf;
int q;
- if (STR_IN_SET(de->d_name, ".", ".."))
+ if (dot_or_dot_dot(de->d_name))
continue;
if (fstatat(dirfd(d), de->d_name, &buf, AT_SYMLINK_NOFOLLOW) < 0) {
diff --git a/src/basic/hexdecoct.c b/src/basic/hexdecoct.c
index 6843aedd0a..2d6e377f0a 100644
--- a/src/basic/hexdecoct.c
+++ b/src/basic/hexdecoct.c
@@ -72,10 +72,10 @@ int unhexchar(char c) {
}
char *hexmem(const void *p, size_t l) {
- char *r, *z;
const uint8_t *x;
+ char *r, *z;
- z = r = malloc(l * 2 + 1);
+ z = r = new(char, l * 2 + 1);
if (!r)
return NULL;
diff --git a/src/basic/path-util.c b/src/basic/path-util.c
index 9a51e0d8bc..1313a52c9c 100644
--- a/src/basic/path-util.c
+++ b/src/basic/path-util.c
@@ -699,10 +699,7 @@ bool filename_is_valid(const char *p) {
if (isempty(p))
return false;
- if (streq(p, "."))
- return false;
-
- if (streq(p, ".."))
+ if (dot_or_dot_dot(p))
return false;
e = strchrnul(p, '/');
@@ -720,14 +717,17 @@ bool path_is_safe(const char *p) {
if (isempty(p))
return false;
- if (streq(p, "..") || startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../"))
+ if (dot_or_dot_dot(p))
+ return false;
+
+ if (startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../"))
return false;
if (strlen(p)+1 > PATH_MAX)
return false;
/* The following two checks are not really dangerous, but hey, they still are confusing */
- if (streq(p, ".") || startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./"))
+ if (startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./"))
return false;
if (strstr(p, "//"))
@@ -892,3 +892,16 @@ int systemd_installation_has_version(const char *root, unsigned minimal_version)
return false;
}
+
+bool dot_or_dot_dot(const char *path) {
+ if (!path)
+ return false;
+ if (path[0] != '.')
+ return false;
+ if (path[1] == 0)
+ return true;
+ if (path[1] != '.')
+ return false;
+
+ return path[2] == 0;
+}
diff --git a/src/basic/path-util.h b/src/basic/path-util.h
index 349cdac7d6..35aef3adc8 100644
--- a/src/basic/path-util.h
+++ b/src/basic/path-util.h
@@ -141,3 +141,5 @@ bool is_device_path(const char *path);
bool is_deviceallow_pattern(const char *path);
int systemd_installation_has_version(const char *root, unsigned minimal_version);
+
+bool dot_or_dot_dot(const char *path);
diff --git a/src/basic/rm-rf.c b/src/basic/rm-rf.c
index 07d42f78dd..08497af729 100644
--- a/src/basic/rm-rf.c
+++ b/src/basic/rm-rf.c
@@ -83,7 +83,7 @@ int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) {
bool is_dir;
struct stat st;
- if (streq(de->d_name, ".") || streq(de->d_name, ".."))
+ if (dot_or_dot_dot(de->d_name))
continue;
if (de->d_type == DT_UNKNOWN ||
diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c
index 77f81a60ba..17e90a8994 100644
--- a/src/basic/socket-util.c
+++ b/src/basic/socket-util.c
@@ -877,7 +877,7 @@ bool ifname_valid(const char *p) {
if (strlen(p) >= IFNAMSIZ)
return false;
- if (STR_IN_SET(p, ".", ".."))
+ if (dot_or_dot_dot(p))
return false;
while (*p) {
diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c
index 44ea6215dc..7cc54a8cdd 100644
--- a/src/boot/efi/boot.c
+++ b/src/boot/efi/boot.c
@@ -1647,7 +1647,7 @@ static EFI_STATUS image_start(EFI_HANDLE parent_image, const Config *config, con
loaded_image->LoadOptionsSize = (StrLen(loaded_image->LoadOptions)+1) * sizeof(CHAR16);
#ifdef SD_BOOT_LOG_TPM
- /* Try to log any options to the TPM, escpecially to catch manually edited options */
+ /* Try to log any options to the TPM, especially to catch manually edited options */
err = tpm_log_event(SD_TPM_PCR,
(EFI_PHYSICAL_ADDRESS) loaded_image->LoadOptions,
loaded_image->LoadOptionsSize, loaded_image->LoadOptions);
diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c
index 1e250f34f4..7c1ffb1bca 100644
--- a/src/boot/efi/stub.c
+++ b/src/boot/efi/stub.c
@@ -100,7 +100,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
cmdline = line;
#ifdef SD_BOOT_LOG_TPM
- /* Try to log any options to the TPM, escpecially manually edited options */
+ /* Try to log any options to the TPM, especially manually edited options */
err = tpm_log_event(SD_TPM_PCR,
(EFI_PHYSICAL_ADDRESS) loaded_image->LoadOptions,
loaded_image->LoadOptionsSize, loaded_image->LoadOptions);
diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c
index b55aa86a40..82b4d9ccb3 100644
--- a/src/cgls/cgls.c
+++ b/src/cgls/cgls.c
@@ -26,7 +26,6 @@
#include "sd-bus.h"
#include "alloc-util.h"
-#include "bus-error.h"
#include "bus-util.h"
#include "cgroup-show.h"
#include "cgroup-util.h"
@@ -35,12 +34,21 @@
#include "output-mode.h"
#include "pager.h"
#include "path-util.h"
+#include "strv.h"
#include "unit-name.h"
#include "util.h"
static bool arg_no_pager = false;
static bool arg_kernel_threads = false;
static bool arg_all = false;
+
+static enum {
+ SHOW_UNIT_NONE,
+ SHOW_UNIT_SYSTEM,
+ SHOW_UNIT_USER,
+} arg_show_unit = SHOW_UNIT_NONE;
+static char **arg_names = NULL;
+
static int arg_full = -1;
static char* arg_machine = NULL;
@@ -51,6 +59,8 @@ static void help(void) {
" --version Show package version\n"
" --no-pager Do not pipe output into a pager\n"
" -a --all Show all groups, including empty\n"
+ " -u --unit Show the subtrees of specifified system units\n"
+ " --user-unit Show the subtrees of specifified user units\n"
" -l --full Do not ellipsize output\n"
" -k Include kernel threads in output\n"
" -M --machine= Show container\n"
@@ -62,15 +72,18 @@ static int parse_argv(int argc, char *argv[]) {
enum {
ARG_NO_PAGER = 0x100,
ARG_VERSION,
+ ARG_USER_UNIT,
};
static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "no-pager", no_argument, NULL, ARG_NO_PAGER },
- { "all", no_argument, NULL, 'a' },
- { "full", no_argument, NULL, 'l' },
- { "machine", required_argument, NULL, 'M' },
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, ARG_VERSION },
+ { "no-pager", no_argument, NULL, ARG_NO_PAGER },
+ { "all", no_argument, NULL, 'a' },
+ { "full", no_argument, NULL, 'l' },
+ { "machine", required_argument, NULL, 'M' },
+ { "unit", optional_argument, NULL, 'u' },
+ { "user-unit", optional_argument, NULL, ARG_USER_UNIT },
{}
};
@@ -79,7 +92,7 @@ static int parse_argv(int argc, char *argv[]) {
assert(argc >= 1);
assert(argv);
- while ((c = getopt_long(argc, argv, "hkalM:", options, NULL)) >= 0)
+ while ((c = getopt_long(argc, argv, "-hkalM:u::", options, NULL)) >= 0)
switch (c) {
@@ -98,6 +111,24 @@ static int parse_argv(int argc, char *argv[]) {
arg_all = true;
break;
+ case 'u':
+ arg_show_unit = SHOW_UNIT_SYSTEM;
+ if (strv_push(&arg_names, optarg) < 0) /* push optarg if not empty */
+ return log_oom();
+ break;
+
+ case ARG_USER_UNIT:
+ arg_show_unit = SHOW_UNIT_USER;
+ if (strv_push(&arg_names, optarg) < 0) /* push optarg if not empty */
+ return log_oom();
+ break;
+
+ case 1:
+ /* positional argument */
+ if (strv_push(&arg_names, optarg) < 0)
+ return log_oom();
+ break;
+
case 'l':
arg_full = true;
break;
@@ -117,51 +148,12 @@ static int parse_argv(int argc, char *argv[]) {
assert_not_reached("Unhandled option");
}
- return 1;
-}
-
-static int get_cgroup_root(char **ret) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
- _cleanup_free_ char *unit = NULL, *path = NULL;
- const char *m;
- int r;
-
- if (!arg_machine) {
- r = cg_get_root_path(ret);
- if (r == -ENOMEDIUM)
- return log_error_errno(r, "Failed to get root control group path: No cgroup filesystem mounted on /sys/fs/cgroup");
- else if (r < 0)
- return log_error_errno(r, "Failed to get root control group path: %m");
-
- return 0;
+ if (arg_machine && arg_show_unit != SHOW_UNIT_NONE) {
+ log_error("Cannot combine --unit or --user-unit with --machine.");
+ return -EINVAL;
}
- m = strjoina("/run/systemd/machines/", arg_machine);
- r = parse_env_file(m, NEWLINE, "SCOPE", &unit, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to load machine data: %m");
-
- path = unit_dbus_path_from_name(unit);
- if (!path)
- return log_oom();
-
- r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, false, &bus);
- if (r < 0)
- return log_error_errno(r, "Failed to create bus connection: %m");
-
- r = sd_bus_get_property_string(
- bus,
- "org.freedesktop.systemd1",
- path,
- unit_dbus_interface_from_name(unit),
- "ControlGroup",
- &error,
- ret);
- if (r < 0)
- return log_error_errno(r, "Failed to query unit control group path: %s", bus_error_message(&error, r));
-
- return 0;
+ return 1;
}
static void show_cg_info(const char *controller, const char *path) {
@@ -194,31 +186,65 @@ int main(int argc, char *argv[]) {
(arg_full > 0) * OUTPUT_FULL_WIDTH |
arg_kernel_threads * OUTPUT_KERNEL_THREADS;
- if (optind < argc) {
+ if (arg_names) {
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_free_ char *root = NULL;
- int i;
+ char **name;
- r = get_cgroup_root(&root);
- if (r < 0)
- goto finish;
-
- for (i = optind; i < argc; i++) {
+ STRV_FOREACH(name, arg_names) {
int q;
- if (path_startswith(argv[i], "/sys/fs/cgroup")) {
+ if (arg_show_unit != SHOW_UNIT_NONE) {
+ /* Command line arguments are unit names */
+ _cleanup_free_ char *cgroup = NULL;
+
+ if (!bus) {
+ /* Connect to the bus only if necessary */
+ r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL,
+ arg_show_unit == SHOW_UNIT_USER,
+ &bus);
+ if (r < 0) {
+ log_error_errno(r, "Failed to create bus connection: %m");
+ goto finish;
+ }
+ }
+
+ q = show_cgroup_get_unit_path_and_warn(bus, *name, &cgroup);
+ if (q < 0)
+ goto failed;
+
+ if (isempty(cgroup)) {
+ log_warning("Unit %s not found.", *name);
+ q = -ENOENT;
+ goto failed;
+ }
+
+ printf("Unit %s (%s):\n", *name, cgroup);
+ fflush(stdout);
+
+ q = show_cgroup_by_path(cgroup, NULL, 0, output_flags);
- printf("Directory %s:\n", argv[i]);
+ } else if (path_startswith(*name, "/sys/fs/cgroup")) {
+
+ printf("Directory %s:\n", *name);
fflush(stdout);
- q = show_cgroup_by_path(argv[i], NULL, 0, output_flags);
+ q = show_cgroup_by_path(*name, NULL, 0, output_flags);
} else {
_cleanup_free_ char *c = NULL, *p = NULL, *j = NULL;
const char *controller, *path;
- r = cg_split_spec(argv[i], &c, &p);
+ if (!root) {
+ /* Query root only if needed, treat error as fatal */
+ r = show_cgroup_get_path_and_warn(arg_machine, NULL, &root);
+ if (r < 0)
+ goto finish;
+ }
+
+ r = cg_split_spec(*name, &c, &p);
if (r < 0) {
- log_error_errno(r, "Failed to split argument %s: %m", argv[i]);
- goto finish;
+ log_error_errno(r, "Failed to split argument %s: %m", *name);
+ goto failed;
}
controller = c ?: SYSTEMD_CGROUP_CONTROLLER;
@@ -239,7 +265,8 @@ int main(int argc, char *argv[]) {
q = show_cgroup(controller, path, NULL, 0, output_flags);
}
- if (q < 0)
+ failed:
+ if (q < 0 && r >= 0)
r = q;
}
@@ -267,7 +294,7 @@ int main(int argc, char *argv[]) {
if (!done) {
_cleanup_free_ char *root = NULL;
- r = get_cgroup_root(&root);
+ r = show_cgroup_get_path_and_warn(arg_machine, NULL, &root);
if (r < 0)
goto finish;
@@ -283,6 +310,7 @@ int main(int argc, char *argv[]) {
finish:
pager_close();
+ free(arg_names); /* don't free the strings */
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c
index af5c3d8695..50ac6a58b0 100644
--- a/src/cgtop/cgtop.c
+++ b/src/cgtop/cgtop.c
@@ -31,6 +31,7 @@
#include "alloc-util.h"
#include "bus-error.h"
#include "bus-util.h"
+#include "cgroup-show.h"
#include "cgroup-util.h"
#include "fd-util.h"
#include "fileio.h"
@@ -862,13 +863,9 @@ static int parse_argv(int argc, char *argv[]) {
assert_not_reached("Unhandled option");
}
- if (optind == argc-1) {
- if (arg_machine) {
- log_error("Specifying a control group path together with the -M option is not allowed");
- return -EINVAL;
- }
+ if (optind == argc - 1)
arg_root = argv[optind];
- } else if (optind < argc) {
+ else if (optind < argc) {
log_error("Too many arguments.");
return -EINVAL;
}
@@ -890,59 +887,6 @@ static const char* counting_what(void) {
return "userspace processes (excl. kernel)";
}
-static int get_cgroup_root(char **ret) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
- _cleanup_free_ char *unit = NULL, *path = NULL;
- const char *m;
- int r;
-
- if (arg_root) {
- char *aux;
-
- aux = strdup(arg_root);
- if (!aux)
- return log_oom();
-
- *ret = aux;
- return 0;
- }
-
- if (!arg_machine) {
- r = cg_get_root_path(ret);
- if (r < 0)
- return log_error_errno(r, "Failed to get root control group path: %m");
-
- return 0;
- }
-
- m = strjoina("/run/systemd/machines/", arg_machine);
- r = parse_env_file(m, NEWLINE, "SCOPE", &unit, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to load machine data: %m");
-
- path = unit_dbus_path_from_name(unit);
- if (!path)
- return log_oom();
-
- r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, false, &bus);
- if (r < 0)
- return log_error_errno(r, "Failed to create bus connection: %m");
-
- r = sd_bus_get_property_string(
- bus,
- "org.freedesktop.systemd1",
- path,
- unit_dbus_interface_from_name(unit),
- "ControlGroup",
- &error,
- ret);
- if (r < 0)
- return log_error_errno(r, "Failed to query unit control group path: %s", bus_error_message(&error, r));
-
- return 0;
-}
-
int main(int argc, char *argv[]) {
int r;
Hashmap *a = NULL, *b = NULL;
@@ -967,11 +911,12 @@ int main(int argc, char *argv[]) {
if (r <= 0)
goto finish;
- r = get_cgroup_root(&root);
+ r = show_cgroup_get_path_and_warn(arg_machine, arg_root, &root);
if (r < 0) {
log_error_errno(r, "Failed to get root control group path: %m");
goto finish;
- }
+ } else
+ log_debug("Cgroup path: %s", root);
a = hashmap_new(&string_hash_ops);
b = hashmap_new(&string_hash_ops);
diff --git a/src/core/execute.c b/src/core/execute.c
index d0faba5a85..47cc4311c1 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -1685,25 +1685,31 @@ static int setup_private_users(uid_t uid, gid_t gid) {
* child then writes the UID mapping, under full privileges. The parent waits for the child to finish and
* continues execution normally. */
- if (uid != 0 && uid_is_valid(uid))
- asprintf(&uid_map,
- "0 0 1\n" /* Map root → root */
- UID_FMT " " UID_FMT " 1\n", /* Map $UID → $UID */
- uid, uid);
- else
+ if (uid != 0 && uid_is_valid(uid)) {
+ r = asprintf(&uid_map,
+ "0 0 1\n" /* Map root → root */
+ UID_FMT " " UID_FMT " 1\n", /* Map $UID → $UID */
+ uid, uid);
+ if (r < 0)
+ return -ENOMEM;
+ } else {
uid_map = strdup("0 0 1\n"); /* The case where the above is the same */
- if (!uid_map)
- return -ENOMEM;
+ if (!uid_map)
+ return -ENOMEM;
+ }
- if (gid != 0 && gid_is_valid(gid))
- asprintf(&gid_map,
- "0 0 1\n" /* Map root → root */
- GID_FMT " " GID_FMT " 1\n", /* Map $GID → $GID */
- gid, gid);
- else
+ if (gid != 0 && gid_is_valid(gid)) {
+ r = asprintf(&gid_map,
+ "0 0 1\n" /* Map root → root */
+ GID_FMT " " GID_FMT " 1\n", /* Map $GID → $GID */
+ gid, gid);
+ if (r < 0)
+ return -ENOMEM;
+ } else {
gid_map = strdup("0 0 1\n"); /* The case where the above is the same */
- if (!gid_map)
- return -ENOMEM;
+ if (!gid_map)
+ return -ENOMEM;
+ }
/* Create a communication channel so that the parent can tell the child when it finished creating the user
* namespace. */
@@ -3096,7 +3102,7 @@ const char* exec_context_fdname(const ExecContext *c, int fd_index) {
int exec_context_named_iofds(Unit *unit, const ExecContext *c, const ExecParameters *p, int named_iofds[3]) {
unsigned i, targets;
- const char *stdio_fdname[3];
+ const char* stdio_fdname[3];
assert(c);
assert(p);
@@ -3109,18 +3115,32 @@ int exec_context_named_iofds(Unit *unit, const ExecContext *c, const ExecParamet
stdio_fdname[i] = exec_context_fdname(c, i);
for (i = 0; i < p->n_fds && targets > 0; i++)
- if (named_iofds[STDIN_FILENO] < 0 && c->std_input == EXEC_INPUT_NAMED_FD && stdio_fdname[STDIN_FILENO] && streq(p->fd_names[i], stdio_fdname[STDIN_FILENO])) {
+ if (named_iofds[STDIN_FILENO] < 0 &&
+ c->std_input == EXEC_INPUT_NAMED_FD &&
+ stdio_fdname[STDIN_FILENO] &&
+ streq(p->fd_names[i], stdio_fdname[STDIN_FILENO])) {
+
named_iofds[STDIN_FILENO] = p->fds[i];
targets--;
- } else if (named_iofds[STDOUT_FILENO] < 0 && c->std_output == EXEC_OUTPUT_NAMED_FD && stdio_fdname[STDOUT_FILENO] && streq(p->fd_names[i], stdio_fdname[STDOUT_FILENO])) {
+
+ } else if (named_iofds[STDOUT_FILENO] < 0 &&
+ c->std_output == EXEC_OUTPUT_NAMED_FD &&
+ stdio_fdname[STDOUT_FILENO] &&
+ streq(p->fd_names[i], stdio_fdname[STDOUT_FILENO])) {
+
named_iofds[STDOUT_FILENO] = p->fds[i];
targets--;
- } else if (named_iofds[STDERR_FILENO] < 0 && c->std_error == EXEC_OUTPUT_NAMED_FD && stdio_fdname[STDERR_FILENO] && streq(p->fd_names[i], stdio_fdname[STDERR_FILENO])) {
+
+ } else if (named_iofds[STDERR_FILENO] < 0 &&
+ c->std_error == EXEC_OUTPUT_NAMED_FD &&
+ stdio_fdname[STDERR_FILENO] &&
+ streq(p->fd_names[i], stdio_fdname[STDERR_FILENO])) {
+
named_iofds[STDERR_FILENO] = p->fds[i];
targets--;
}
- return (targets == 0 ? 0 : -ENOENT);
+ return targets == 0 ? 0 : -ENOENT;
}
int exec_context_load_environment(Unit *unit, const ExecContext *c, char ***l) {
diff --git a/src/core/killall.c b/src/core/killall.c
index b3aa22adc5..7a9df546ee 100644
--- a/src/core/killall.c
+++ b/src/core/killall.c
@@ -66,29 +66,26 @@ static bool ignore_proc(pid_t pid, bool warn_rootfs) {
if (count <= 0)
return true;
- /* Processes with argv[0][0] = '@' we ignore from the killing
- * spree.
+ /* Processes with argv[0][0] = '@' we ignore from the killing spree.
*
* http://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons */
- if (c == '@' && warn_rootfs) {
- _cleanup_free_ char *comm = NULL;
+ if (c != '@')
+ return false;
- r = pid_from_same_root_fs(pid);
- if (r < 0)
- return true;
+ if (warn_rootfs &&
+ pid_from_same_root_fs(pid) == 0) {
+
+ _cleanup_free_ char *comm = NULL;
get_process_comm(pid, &comm);
- if (r)
- log_notice("Process " PID_FMT " (%s) has been marked to be excluded from killing. It is "
- "running from the root file system, and thus likely to block re-mounting of the "
- "root file system to read-only. Please consider moving it into an initrd file "
- "system instead.", pid, strna(comm));
- return true;
- } else if (c == '@')
- return true;
+ log_notice("Process " PID_FMT " (%s) has been marked to be excluded from killing. It is "
+ "running from the root file system, and thus likely to block re-mounting of the "
+ "root file system to read-only. Please consider moving it into an initrd file "
+ "system instead.", pid, strna(comm));
+ }
- return false;
+ return true;
}
static void wait_for_children(Set *pids, sigset_t *mask) {
diff --git a/src/core/timer.c b/src/core/timer.c
index 5ee14669d2..d7441d638f 100644
--- a/src/core/timer.c
+++ b/src/core/timer.c
@@ -232,7 +232,7 @@ static void timer_dump(Unit *u, FILE *f, const char *prefix) {
if (v->base == TIMER_CALENDAR) {
_cleanup_free_ char *p = NULL;
- calendar_spec_to_string(v->calendar_spec, &p);
+ (void) calendar_spec_to_string(v->calendar_spec, &p);
fprintf(f,
"%s%s: %s\n",
diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c
index cefd1b85df..91c653312a 100644
--- a/src/cryptsetup/cryptsetup.c
+++ b/src/cryptsetup/cryptsetup.c
@@ -594,7 +594,7 @@ static int help(void) {
int main(int argc, char *argv[]) {
struct crypt_device *cd = NULL;
- int r;
+ int r = -EINVAL;
if (argc <= 1) {
r = help();
@@ -603,7 +603,6 @@ int main(int argc, char *argv[]) {
if (argc < 3) {
log_error("This program requires at least two arguments.");
- r = -EINVAL;
goto finish;
}
@@ -750,7 +749,6 @@ int main(int argc, char *argv[]) {
} else {
log_error("Unknown verb %s.", argv[1]);
- r = -EINVAL;
goto finish;
}
diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c
index e61ef8f249..b958070c90 100644
--- a/src/gpt-auto-generator/gpt-auto-generator.c
+++ b/src/gpt-auto-generator/gpt-auto-generator.c
@@ -658,7 +658,7 @@ static int get_block_device_harder(const char *path, dev_t *dev) {
FOREACH_DIRENT_ALL(de, d, return -errno) {
- if (STR_IN_SET(de->d_name, ".", ".."))
+ if (dot_or_dot_dot(de->d_name))
continue;
if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN))
diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
index 93b9ff2da0..ef87b176fa 100644
--- a/src/journal/journal-file.c
+++ b/src/journal/journal-file.c
@@ -42,6 +42,7 @@
#include "sd-event.h"
#include "set.h"
#include "string-util.h"
+#include "strv.h"
#include "xattr-util.h"
#define DEFAULT_DATA_HASH_TABLE_SIZE (2047ULL*sizeof(HashItem))
@@ -507,42 +508,58 @@ static int journal_file_refresh_header(JournalFile *f) {
return r;
}
-static int journal_file_verify_header(JournalFile *f) {
+static bool warn_wrong_flags(const JournalFile *f, bool compatible) {
+ const uint32_t any = compatible ? HEADER_COMPATIBLE_ANY : HEADER_INCOMPATIBLE_ANY,
+ supported = compatible ? HEADER_COMPATIBLE_SUPPORTED : HEADER_INCOMPATIBLE_SUPPORTED;
+ const char *type = compatible ? "compatible" : "incompatible";
uint32_t flags;
+ flags = le32toh(compatible ? f->header->compatible_flags : f->header->incompatible_flags);
+
+ if (flags & ~supported) {
+ if (flags & ~any)
+ log_debug("Journal file %s has unknown %s flags 0x%"PRIx32,
+ f->path, type, flags & ~any);
+ flags = (flags & any) & ~supported;
+ if (flags) {
+ const char* strv[3];
+ unsigned n = 0;
+ _cleanup_free_ char *t = NULL;
+
+ if (compatible && (flags & HEADER_COMPATIBLE_SEALED))
+ strv[n++] = "sealed";
+ if (!compatible && (flags & HEADER_INCOMPATIBLE_COMPRESSED_XZ))
+ strv[n++] = "xz-compressed";
+ if (!compatible && (flags & HEADER_INCOMPATIBLE_COMPRESSED_LZ4))
+ strv[n++] = "lz4-compressed";
+ strv[n] = NULL;
+ assert(n < ELEMENTSOF(strv));
+
+ t = strv_join((char**) strv, ", ");
+ log_debug("Journal file %s uses %s %s %s disabled at compilation time.",
+ f->path, type, n > 1 ? "flags" : "flag", strnull(t));
+ }
+ return true;
+ }
+
+ return false;
+}
+
+static int journal_file_verify_header(JournalFile *f) {
assert(f);
assert(f->header);
if (memcmp(f->header->signature, HEADER_SIGNATURE, 8))
return -EBADMSG;
- /* In both read and write mode we refuse to open files with
- * incompatible flags we don't know */
- flags = le32toh(f->header->incompatible_flags);
- if (flags & ~HEADER_INCOMPATIBLE_SUPPORTED) {
- if (flags & ~HEADER_INCOMPATIBLE_ANY)
- log_debug("Journal file %s has unknown incompatible flags %"PRIx32,
- f->path, flags & ~HEADER_INCOMPATIBLE_ANY);
- flags = (flags & HEADER_INCOMPATIBLE_ANY) & ~HEADER_INCOMPATIBLE_SUPPORTED;
- if (flags)
- log_debug("Journal file %s uses incompatible flags %"PRIx32
- " disabled at compilation time.", f->path, flags);
+ /* In both read and write mode we refuse to open files with incompatible
+ * flags we don't know. */
+ if (warn_wrong_flags(f, false))
return -EPROTONOSUPPORT;
- }
- /* When open for writing we refuse to open files with
- * compatible flags, too */
- flags = le32toh(f->header->compatible_flags);
- if (f->writable && (flags & ~HEADER_COMPATIBLE_SUPPORTED)) {
- if (flags & ~HEADER_COMPATIBLE_ANY)
- log_debug("Journal file %s has unknown compatible flags %"PRIx32,
- f->path, flags & ~HEADER_COMPATIBLE_ANY);
- flags = (flags & HEADER_COMPATIBLE_ANY) & ~HEADER_COMPATIBLE_SUPPORTED;
- if (flags)
- log_debug("Journal file %s uses compatible flags %"PRIx32
- " disabled at compilation time.", f->path, flags);
+ /* When open for writing we refuse to open files with compatible flags, too. */
+ if (f->writable && warn_wrong_flags(f, true))
return -EPROTONOSUPPORT;
- }
if (f->header->state >= _STATE_MAX)
return -EBADMSG;
@@ -3087,13 +3104,18 @@ int journal_file_open(
}
}
- if (fname)
+ if (fname) {
f->path = strdup(fname);
- else /* If we don't know the path, fill in something explanatory and vaguely useful */
- asprintf(&f->path, "/proc/self/%i", fd);
- if (!f->path) {
- r = -ENOMEM;
- goto fail;
+ if (!f->path) {
+ r = -ENOMEM;
+ goto fail;
+ }
+ } else {
+ /* If we don't know the path, fill in something explanatory and vaguely useful */
+ if (asprintf(&f->path, "/proc/self/%i", fd) < 0) {
+ r = -ENOMEM;
+ goto fail;
+ }
}
f->chain_cache = ordered_hashmap_new(&uint64_hash_ops);
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
index 2a5f2b37e8..2639fd6cf5 100644
--- a/src/journal/journalctl.c
+++ b/src/journal/journalctl.c
@@ -1910,7 +1910,9 @@ static int access_check(sd_journal *j) {
break;
case EPROTONOSUPPORT:
- log_warning_errno(err, "Journal file %s uses an unsupported feature, ignoring file.", path);
+ log_warning_errno(err, "Journal file %1$s uses an unsupported feature, ignoring file.\n"
+ "Use SYSTEMD_LOG_LEVEL=debug journalctl --file=%1$s to see the details.",
+ path);
break;
case EBADMSG:
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index 4c618ed19e..1aac7ae979 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -240,7 +240,6 @@ static int list_seats(int argc, char *argv[], void *userdata) {
sd_bus *bus = userdata;
unsigned k = 0;
int r;
-
assert(bus);
assert(argv);
@@ -280,35 +279,17 @@ static int list_seats(int argc, char *argv[], void *userdata) {
}
static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit, pid_t leader) {
+ _cleanup_free_ char *cgroup = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_free_ char *path = NULL;
- const char *cgroup;
unsigned c;
int r;
assert(bus);
assert(unit);
- path = unit_dbus_path_from_name(unit);
- if (!path)
- return log_oom();
-
- r = sd_bus_get_property(
- bus,
- "org.freedesktop.systemd1",
- path,
- interface,
- "ControlGroup",
- &error,
- &reply,
- "s");
- if (r < 0)
- return log_error_errno(r, "Failed to query ControlGroup: %s", bus_error_message(&error, r));
-
- r = sd_bus_message_read(reply, "s", &cgroup);
+ r = show_cgroup_get_unit_path_and_warn(bus, unit, &cgroup);
if (r < 0)
- return bus_log_parse_error(r);
+ return r;
if (isempty(cgroup))
return 0;
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 3873bf3e96..ad44ca290e 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -2396,13 +2396,9 @@ static int method_set_wall_message(
if (r == 0)
return 1; /* Will call us back */
- if (isempty(wall_message))
- m->wall_message = mfree(m->wall_message);
- else {
- r = free_and_strdup(&m->wall_message, wall_message);
- if (r < 0)
- return log_oom();
- }
+ r = free_and_strdup(&m->wall_message, empty_to_null(wall_message));
+ if (r < 0)
+ return log_oom();
m->enable_wall_messages = enable_wall_messages;
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index 31a40d47c3..4f5f659c7c 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -477,35 +477,17 @@ static int list_images(int argc, char *argv[], void *userdata) {
}
static int show_unit_cgroup(sd_bus *bus, const char *unit, pid_t leader) {
+ _cleanup_free_ char *cgroup = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_free_ char *path = NULL;
- const char *cgroup;
int r;
unsigned c;
assert(bus);
assert(unit);
- path = unit_dbus_path_from_name(unit);
- if (!path)
- return log_oom();
-
- r = sd_bus_get_property(
- bus,
- "org.freedesktop.systemd1",
- path,
- unit_dbus_interface_from_name(unit),
- "ControlGroup",
- &error,
- &reply,
- "s");
- if (r < 0)
- return log_error_errno(r, "Failed to query ControlGroup: %s", bus_error_message(&error, r));
-
- r = sd_bus_message_read(reply, "s", &cgroup);
+ r = show_cgroup_get_unit_path_and_warn(bus, unit, &cgroup);
if (r < 0)
- return bus_log_parse_error(r);
+ return r;
if (isempty(cgroup))
return 0;
diff --git a/src/nspawn/nspawn-patch-uid.c b/src/nspawn/nspawn-patch-uid.c
index ded5866d05..1a3f129db0 100644
--- a/src/nspawn/nspawn-patch-uid.c
+++ b/src/nspawn/nspawn-patch-uid.c
@@ -375,7 +375,7 @@ static int recurse_fd(int fd, bool donate_fd, const struct stat *st, uid_t shift
FOREACH_DIRENT_ALL(de, d, r = -errno; goto finish) {
struct stat fst;
- if (STR_IN_SET(de->d_name, ".", ".."))
+ if (dot_or_dot_dot(de->d_name))
continue;
if (fstatat(dirfd(d), de->d_name, &fst, AT_SYMLINK_NOFOLLOW) < 0) {
diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c
index 0954641c20..667774b906 100644
--- a/src/resolve/resolved-manager.c
+++ b/src/resolve/resolved-manager.c
@@ -1349,7 +1349,7 @@ void manager_cleanup_saved_user(Manager *m) {
if (!IN_SET(de->d_type, DT_UNKNOWN, DT_REG))
continue;
- if (STR_IN_SET(de->d_name, ".", ".."))
+ if (dot_or_dot_dot(de->d_name))
continue;
r = parse_ifindex(de->d_name, &ifindex);
diff --git a/src/shared/cgroup-show.c b/src/shared/cgroup-show.c
index 5d21742a09..8765cf2f49 100644
--- a/src/shared/cgroup-show.c
+++ b/src/shared/cgroup-show.c
@@ -24,10 +24,15 @@
#include <stdlib.h>
#include <string.h>
+#include <systemd/sd-bus.h>
+
#include "alloc-util.h"
+#include "bus-error.h"
+#include "bus-util.h"
#include "cgroup-show.h"
#include "cgroup-util.h"
#include "fd-util.h"
+#include "fileio.h"
#include "format-util.h"
#include "locale-util.h"
#include "macro.h"
@@ -36,6 +41,7 @@
#include "process-util.h"
#include "string-util.h"
#include "terminal-util.h"
+#include "unit-name.h"
static void show_pid_array(
pid_t pids[],
@@ -73,7 +79,7 @@ static void show_pid_array(
for (i = 0; i < n_pids; i++) {
_cleanup_free_ char *t = NULL;
- get_process_cmdline(pids[i], n_columns, true, &t);
+ (void) get_process_cmdline(pids[i], n_columns, true, &t);
if (extra)
printf("%s%s ", prefix, special_glyph(TRIANGULAR_BULLET));
@@ -310,3 +316,81 @@ int show_cgroup_and_extra_by_spec(
return show_cgroup_and_extra(controller, path, prefix, n_columns, extra_pids, n_extra_pids, flags);
}
+
+int show_cgroup_get_unit_path_and_warn(
+ sd_bus *bus,
+ const char *unit,
+ char **ret) {
+
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_free_ char *path = NULL;
+ int r;
+
+ path = unit_dbus_path_from_name(unit);
+ if (!path)
+ return log_oom();
+
+ r = sd_bus_get_property_string(
+ bus,
+ "org.freedesktop.systemd1",
+ path,
+ unit_dbus_interface_from_name(unit),
+ "ControlGroup",
+ &error,
+ ret);
+ if (r < 0)
+ return log_error_errno(r, "Failed to query unit control group path: %s",
+ bus_error_message(&error, r));
+
+ return 0;
+}
+
+int show_cgroup_get_path_and_warn(
+ const char *machine,
+ const char *prefix,
+ char **ret) {
+
+ int r;
+ _cleanup_free_ char *root = NULL;
+
+ if (machine) {
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+ _cleanup_free_ char *unit = NULL;
+ const char *m;
+
+ m = strjoina("/run/systemd/machines/", machine);
+ r = parse_env_file(m, NEWLINE, "SCOPE", &unit, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to load machine data: %m");
+
+ r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, false, &bus);
+ if (r < 0)
+ return log_error_errno(r, "Failed to create bus connection: %m");
+
+ r = show_cgroup_get_unit_path_and_warn(bus, unit, &root);
+ if (r < 0)
+ return r;
+ } else {
+ r = cg_get_root_path(&root);
+ if (r == -ENOMEDIUM)
+ return log_error_errno(r, "Failed to get root control group path.\n"
+ "No cgroup filesystem mounted on /sys/fs/cgroup");
+ else if (r < 0)
+ return log_error_errno(r, "Failed to get root control group path: %m");
+ }
+
+ if (prefix) {
+ char *t;
+
+ t = strjoin(root, prefix);
+ if (!t)
+ return log_oom();
+
+ *ret = t;
+ } else {
+ *ret = root;
+ root = NULL;
+ }
+
+ return 0;
+}
diff --git a/src/shared/cgroup-show.h b/src/shared/cgroup-show.h
index 5c1d6e6d98..736f0f34c8 100644
--- a/src/shared/cgroup-show.h
+++ b/src/shared/cgroup-show.h
@@ -22,6 +22,8 @@
#include <stdbool.h>
#include <sys/types.h>
+#include <systemd/sd-bus.h>
+
#include "logs-show.h"
#include "output-mode.h"
@@ -30,3 +32,12 @@ int show_cgroup(const char *controller, const char *path, const char *prefix, un
int show_cgroup_and_extra_by_spec(const char *spec, const char *prefix, unsigned n_columns, const pid_t extra_pids[], unsigned n_extra_pids, OutputFlags flags);
int show_cgroup_and_extra(const char *controller, const char *path, const char *prefix, unsigned n_columns, const pid_t extra_pids[], unsigned n_extra_pids, OutputFlags flags);
+
+int show_cgroup_get_unit_path_and_warn(
+ sd_bus *bus,
+ const char *unit,
+ char **ret);
+int show_cgroup_get_path_and_warn(
+ const char *machine,
+ const char *prefix,
+ char **ret);
diff --git a/src/shared/clean-ipc.c b/src/shared/clean-ipc.c
index f2d1555c13..f59f6f23ae 100644
--- a/src/shared/clean-ipc.c
+++ b/src/shared/clean-ipc.c
@@ -225,7 +225,7 @@ static int clean_posix_shm_internal(DIR *dir, uid_t uid, gid_t gid) {
FOREACH_DIRENT_ALL(de, dir, goto fail) {
struct stat st;
- if (STR_IN_SET(de->d_name, "..", "."))
+ if (dot_or_dot_dot(de->d_name))
continue;
if (fstatat(dirfd(dir), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
@@ -310,7 +310,7 @@ static int clean_posix_mq(uid_t uid, gid_t gid) {
struct stat st;
char fn[1+strlen(de->d_name)+1];
- if (STR_IN_SET(de->d_name, "..", "."))
+ if (dot_or_dot_dot(de->d_name))
continue;
if (fstatat(dirfd(dir), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
diff --git a/src/system-update-generator/system-update-generator.c b/src/system-update-generator/system-update-generator.c
index 6ffb169b21..f1514c9638 100644
--- a/src/system-update-generator/system-update-generator.c
+++ b/src/system-update-generator/system-update-generator.c
@@ -22,6 +22,7 @@
#include "fs-util.h"
#include "log.h"
+#include "proc-cmdline.h"
#include "special.h"
#include "string-util.h"
#include "util.h"
@@ -47,11 +48,27 @@ static int generate_symlink(void) {
if (symlink(SYSTEM_DATA_UNIT_PATH "/system-update.target", p) < 0)
return log_error_errno(errno, "Failed to create symlink %s: %m", p);
+ return 1;
+}
+
+static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
+ assert(key);
+
+ /* Check if a run level is specified on the kernel command line. The
+ * command line has higher priority than any on-disk configuration, so
+ * it'll make any symlink we create moot.
+ */
+
+ if (streq(key, "systemd.unit") && !proc_cmdline_value_missing(key, value))
+ log_warning("Offline system update overriden by kernel command line systemd.unit= setting");
+ else if (!value && runlevel_to_target(key))
+ log_warning("Offline system update overriden by runlevel \"%s\" on the kernel command line", key);
+
return 0;
}
int main(int argc, char *argv[]) {
- int r;
+ int r, k;
if (argc > 1 && argc != 4) {
log_error("This program takes three or no arguments.");
@@ -69,5 +86,11 @@ int main(int argc, char *argv[]) {
r = generate_symlink();
+ if (r > 0) {
+ k = proc_cmdline_parse(parse_proc_cmdline_item, NULL, 0);
+ if (k < 0)
+ log_warning_errno(k, "Failed to parse kernel command line, ignoring: %m");
+ }
+
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index a20ca1bcb5..8f80559baf 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -6937,6 +6937,7 @@ static void systemctl_help(void) {
" -a --all Show all properties/all units currently in memory,\n"
" including dead/empty ones. To list all units installed on\n"
" the system, use the 'list-unit-files' command instead.\n"
+ " --failed Same as --state=failed\n"
" -l --full Don't ellipsize unit names on output\n"
" -r --recursive Show unit list of host and local containers\n"
" --reverse Show reverse dependencies with 'list-dependencies'\n"
diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c
index 4cb465d0d2..e774f567e0 100644
--- a/src/test/test-fs-util.c
+++ b/src/test/test-fs-util.c
@@ -305,12 +305,23 @@ static void test_var_tmp(void) {
}
}
+static void test_dot_or_dot_dot(void) {
+ assert_se(!dot_or_dot_dot(NULL));
+ assert_se(!dot_or_dot_dot(""));
+ assert_se(!dot_or_dot_dot("xxx"));
+ assert_se(dot_or_dot_dot("."));
+ assert_se(dot_or_dot_dot(".."));
+ assert_se(!dot_or_dot_dot(".foo"));
+ assert_se(!dot_or_dot_dot("..foo"));
+}
+
int main(int argc, char *argv[]) {
test_unlink_noerrno();
test_readlink_and_make_absolute();
test_get_files_in_directory();
test_var_tmp();
test_chase_symlinks();
+ test_dot_or_dot_dot();
return 0;
}
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index f4ce9791fb..c4f4d46ca1 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -385,7 +385,7 @@ static int dir_cleanup(
usec_t age;
_cleanup_free_ char *sub_path = NULL;
- if (STR_IN_SET(dent->d_name, ".", ".."))
+ if (dot_or_dot_dot(dent->d_name))
continue;
if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) {
@@ -1070,9 +1070,7 @@ static int item_do_children(Item *i, const char *path, action_t action) {
_cleanup_free_ char *p = NULL;
int q;
- errno = 0;
-
- if (STR_IN_SET(de->d_name, ".", ".."))
+ if (dot_or_dot_dot(de->d_name))
continue;
p = strjoin(path, "/", de->d_name);